From ef2592729ca2ba81ba88cd4203e1a68c698a26ee Mon Sep 17 00:00:00 2001 From: Willi Braun Date: Thu, 1 Feb 2018 09:53:59 +0100 Subject: [PATCH] added DAEMode module Belonging to [master]: - OpenModelica/OMCompiler#2142 --- Compiler/BackEnd/BackendDAE.mo | 24 + Compiler/BackEnd/BackendDAECreate.mo | 3 +- Compiler/BackEnd/BackendDAEOptimize.mo | 146 ++++++ Compiler/BackEnd/BackendDAEUtil.mo | 168 ++++++- Compiler/BackEnd/BackendDump.mo | 2 + Compiler/BackEnd/BackendEquation.mo | 23 + Compiler/BackEnd/BackendVariable.mo | 62 ++- Compiler/BackEnd/CommonSubExpression.mo | 2 +- Compiler/BackEnd/DAEMode.mo | 322 ++++++++++++++ Compiler/BackEnd/SymbolicJacobian.mo | 58 +++ Compiler/Script/CevalScriptBackend.mo | 55 ++- Compiler/SimCode/SimCode.mo | 3 +- Compiler/SimCode/SimCodeMain.mo | 417 +++++++++++++++++- Compiler/SimCode/SimCodeUtil.mo | 115 +++-- Compiler/Template/CodegenC.tpl | 19 +- Compiler/Template/CodegenCFunctions.tpl | 1 + Compiler/Template/CodegenCpp.tpl | 10 +- Compiler/Template/CodegenUtil.tpl | 1 + Compiler/Template/SimCodeTV.mo | 4 +- Compiler/Util/Config.mo | 6 + Compiler/Util/Flags.mo | 27 +- Compiler/boot/LoadCompilerSources.mos | 1 + .../c/simulation/solver/ida_solver.c | 48 +- SimulationRuntime/c/simulation_data.h | 6 + 24 files changed, 1425 insertions(+), 98 deletions(-) create mode 100644 Compiler/BackEnd/DAEMode.mo diff --git a/Compiler/BackEnd/BackendDAE.mo b/Compiler/BackEnd/BackendDAE.mo index 6d7aee235e5..b84f1b8a5d5 100644 --- a/Compiler/BackEnd/BackendDAE.mo +++ b/Compiler/BackEnd/BackendDAE.mo @@ -131,6 +131,7 @@ uniontype Shared "Data shared for all equation-systems" SymbolicJacobians symjacs "Symbolic Jacobians"; ExtraInfo info "contains extra info that we send around like the model name"; PartitionsInfo partitionsInfo; + BackendDAEModeData daeModeData "DAEMode Data"; end SHARED; end Shared; @@ -180,6 +181,7 @@ uniontype BackendDAEType "BackendDAEType to indicate different types of BackendD record PARAMETERSYSTEM "Type for parameter system BackendDAE.DAE" end PARAMETERSYSTEM; record INITIALSYSTEM "Type for initial system BackendDAE.DAE" end INITIALSYSTEM; record INLINESYSTEM "Type for inline system BackendDAE.DAE" end INLINESYSTEM; + record DAEMODESYSTEM "Type for DAEmode system BackendDAE.DAE" end DAEMODESYSTEM; end BackendDAEType; // @@ -270,6 +272,7 @@ uniontype VarKind "variable kind" record ALG_STATE end ALG_STATE; // algebraic state used by inline solver record ALG_STATE_OLD end ALG_STATE_OLD; // algebraic state old value used by inline solver record DAE_RESIDUAL_VAR end DAE_RESIDUAL_VAR; // variable kind used for DAEmode + record DAE_AUX_VAR end DAE_AUX_VAR; // auxiliary variable used for DAEmode end VarKind; public uniontype TearingSelect @@ -291,6 +294,10 @@ public uniontype EquationKind "equation kind" record CLOCKED_EQUATION Integer clk; end CLOCKED_EQUATION; + record DISCRETE_EQUATION + end DISCRETE_EQUATION; + record AUX_EQUATION + end AUX_EQUATION; record UNKNOWN_EQUATION_KIND end UNKNOWN_EQUATION_KIND; end EquationKind; @@ -835,6 +842,23 @@ public uniontype CompInfo"types to count operations for the components" end CompInfo; +public +uniontype BackendDAEModeData + record BDAE_MODE_DATA + Integer numAuxVars; + list auxVars; + + Integer numResVars; + list resVars; + + Integer numAuxEqns; + list auxEqns; + + Integer numResEqns; + list resEqns; + end BDAE_MODE_DATA; +end BackendDAEModeData; +constant BackendDAEModeData emptyDAEModeData = BDAE_MODE_DATA(0,{},0,{},0,{},0,{}); annotation(__OpenModelica_Interface="backend"); end BackendDAE; diff --git a/Compiler/BackEnd/BackendDAECreate.mo b/Compiler/BackEnd/BackendDAECreate.mo index fc15aa1642b..dd23ed1d5fb 100644 --- a/Compiler/BackEnd/BackendDAECreate.mo +++ b/Compiler/BackEnd/BackendDAECreate.mo @@ -166,7 +166,8 @@ algorithm extObjCls, BackendDAE.SIMULATION(), symjacs,inExtraInfo, - BackendDAEUtil.emptyPartitionsInfo() + BackendDAEUtil.emptyPartitionsInfo(), + BackendDAE.emptyDAEModeData )); BackendDAEUtil.checkBackendDAEWithErrorMsg(outBackendDAE); BackendDAEUtil.checkIncidenceMatrixSolvability(syst, functionTree); diff --git a/Compiler/BackEnd/BackendDAEOptimize.mo b/Compiler/BackEnd/BackendDAEOptimize.mo index fccf3015e95..3f9172717b0 100644 --- a/Compiler/BackEnd/BackendDAEOptimize.mo +++ b/Compiler/BackEnd/BackendDAEOptimize.mo @@ -5169,6 +5169,152 @@ algorithm end matchcontinue; end introDerAlias; + +// ============================================================================= +// section for replaceDerCall +// +// ============================================================================= + +public function replaceDerCalls +" This module replaces all der(cref)-calls by $DER.cref crefs expression." + input BackendDAE.BackendDAE inDAE; + output BackendDAE.BackendDAE outDAE; +algorithm + outDAE := BackendDAEUtil.mapEqSystem(inDAE, replaceDerCallWork); +end replaceDerCalls; + +protected function replaceDerCallWork + input BackendDAE.EqSystem inSyst; + input BackendDAE.Shared shared; + output BackendDAE.EqSystem osyst; + output BackendDAE.Shared oshared = shared; +protected + BackendDAE.Variables vars; + BackendDAE.EquationArray eqns; + list eqnsList; +algorithm + osyst := match inSyst + local + BackendDAE.EqSystem syst; + BackendDAE.Variables localKnowns; + case syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) + algorithm + (eqns, vars) := + BackendEquation.traverseEquationArray_WithUpdate(eqns, traverserreplaceDerCall, vars); + (localKnowns, vars) := BackendVariable.traverseBackendDAEVars(vars, + moveStatesVariables, (oshared.localKnownVars, vars)); + oshared.localKnownVars := localKnowns; + syst.orderedEqs := eqns; syst.orderedVars := vars; + then syst; + end match; +end replaceDerCallWork; + +protected function traverserreplaceDerCall " + Help function to e.g. replaceDerCall" + input BackendDAE.Equation inEq; + input BackendDAE.Variables inVars; + output BackendDAE.Equation outEq; + output BackendDAE.Variables outVars = inVars; +protected + BackendDAE.Equation e; + BackendDAE.Variables vars; + list ops; +algorithm + (e, ops) := BackendEquation.traverseExpsOfEquation(inEq, traverserreplaceDerCallExp, {}); + outEq := List.foldr(ops, BackendEquation.addOperation, e); +end traverserreplaceDerCall; + +protected function traverserreplaceDerCallExp " + Help function to e.g. traverserreplaceDerCall" + input DAE.Exp inExp; + input list tpl; + output DAE.Exp outExp; + output list outTpl; +protected + DAE.Exp e, e1; + tuple ext_arg; + BackendDAE.Variables vars; + list ops; + DAE.FunctionTree funcs; + Boolean b, addVars; + BackendDAE.Shared shared; + list eqnLst; +algorithm + e := inExp; + ops := tpl; + (e1, b) := Expression.traverseExpBottomUp(e, replaceDerCall, false); + ops := List.consOnTrue(b, DAE.SUBSTITUTION({e1}, e), ops); + outExp := e1; + outTpl := ops; +end traverserreplaceDerCallExp; + +protected function replaceDerCall " + Help function to e.g. traverserreplaceDerCallExp" + input DAE.Exp inExp; + input Boolean itpl; + output DAE.Exp outExp; + output Boolean tpl; +algorithm + (outExp,tpl) := matchcontinue (inExp, itpl) + local + BackendDAE.Variables vars; + DAE.ComponentRef cr,cref; + DAE.Type ty; + String str; + BackendDAE.Shared shared; + list varlst; + BackendDAE.Var v, v1; + Boolean b, addVar; + DAE.FunctionTree funcs; + list eqnLst; + Integer numVars; + list expLst; + String str; + + case (DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(componentRef=cr, ty=ty)}), _) equation + cref = ComponentReference.crefPrefixDer(cr); + outExp = DAE.CREF(cref,ty); + then (outExp, true); + + case (DAE.CALL(path=Absyn.IDENT(name="der")), _) equation + str = "BackendDAEOptimize.replaceDerCall failed for: " + ExpressionDump.printExpStr(inExp) + "\n"; + Error.addMessage(Error.INTERNAL_ERROR, {str}); + then fail(); + + else (inExp, itpl); + end matchcontinue; +end replaceDerCall; + +protected function moveStatesVariables + input BackendDAE.Var inVar; + input tuple inTpl; + output BackendDAE.Var outVar = inVar; + output tuple outTpl = inTpl; +algorithm + _ := match(inVar) + local + DAE.ComponentRef cref; + BackendDAE.Var newVar; + BackendDAE.Variables localKnowns, newVars; + case(BackendDAE.VAR(varKind = BackendDAE.STATE(), varName=cref)) algorithm + (localKnowns, newVars) := inTpl; + // remove the state from variables + newVars := BackendVariable.deleteVar(cref, newVars); + // push it to the local knows + localKnowns := BackendVariable.addVar(inVar, localKnowns); + + cref := ComponentReference.crefPrefixDer(cref); + newVar := BackendVariable.copyVarNewName(cref, inVar); + newVar := BackendVariable.setVarKind(newVar, BackendDAE.STATE_DER()); + + newVars := BackendVariable.addVar(newVar, newVars); + outTpl := (localKnowns, newVars); + then (); + else then(); + end match; +end moveStatesVariables; + + // ============================================================================= // replace expression with rewritten expression // diff --git a/Compiler/BackEnd/BackendDAEUtil.mo b/Compiler/BackEnd/BackendDAEUtil.mo index 422fa335de0..3a2730ac87a 100644 --- a/Compiler/BackEnd/BackendDAEUtil.mo +++ b/Compiler/BackEnd/BackendDAEUtil.mo @@ -75,6 +75,7 @@ import CommonSubExpression; import ComponentReference; import Config; import DAEDump; +import DAEMode; import DAEUtil; import Debug; import Differentiate; @@ -6924,7 +6925,7 @@ algorithm outDAE := preOptimizeDAE(inDAE, preOptModules); end preOptimizeBackendDAE; -protected function preOptimizeDAE " +public function preOptimizeDAE " This function runs the pre-optimization modules." input BackendDAE.BackendDAE inDAE; input list> inPreOptModules; @@ -6975,7 +6976,7 @@ algorithm outDAE := causalizeDAE(inDAE,inMatchingOptions,matchingAlgorithm,indexReductionMethod,true); end transformBackendDAE; -protected function causalizeDAE " +public function causalizeDAE " Run the matching Algorithm. In case of a DAE a DAE handler is used to reduce the index of the DAE." input BackendDAE.BackendDAE inDAE; @@ -7249,6 +7250,130 @@ algorithm //fcall2(Flags.DUMP_EQNINORDER, BackendDump.dumpEqnsSolved, outDAE, "system for jacobians"); end getSolvedSystemforJacobians; +public function getOptimizesDAEModeSystem + "Run the equation system pipeline." + input BackendDAE.BackendDAE inDAE; + input String fileNamePrefix; + input Option> strPreOptModules = NONE(); + input Option strmatchingAlgorithm = NONE(); + input Option strdaeHandler = NONE(); + input Option> strPostOptModules = NONE(); + output BackendDAE.BackendDAE outSimDAE; + output BackendDAE.BackendDAE outInitDAE; + output Option outInlineData; + output list outRemovedInitialEquationLst; +protected + BackendDAE.BackendDAE dae, simDAE; + list> preOptModules; + list> postOptModules; + tuple daeHandler; + tuple matchingAlgorithm; + BackendDAE.InlineData inlineData; + BackendDAE.Variables globalKnownVars; + Integer numCheckpoints; + DAE.FunctionTree funcTree; +algorithm + numCheckpoints:=ErrorExt.getNumCheckpoints(); + try + StackOverflow.clearStacktraceMessages(); + preOptModules := getPreOptModules(strPreOptModules); + postOptModules := getPostOptModules(strPostOptModules); + matchingAlgorithm := getMatchingAlgorithm(strmatchingAlgorithm); + daeHandler := getIndexReductionMethod(strdaeHandler); + + if Flags.isSet(Flags.DUMP_DAE_LOW) then + BackendDump.dumpBackendDAE(inDAE, "dumpdaelow"); + if Flags.isSet(Flags.ADDITIONAL_GRAPHVIZ_DUMP) then + BackendDump.graphvizIncidenceMatrix(inDAE, "dumpdaelow"); + end if; + end if; + + // pre-optimization phase + dae := preOptimizeDAE(inDAE, preOptModules); + + execStat("pre-optimization done (n="+String(daeSize(dae))+")"); + // transformation phase (matching and sorting using index reduction method) + dae := causalizeDAE(dae, NONE(), matchingAlgorithm, daeHandler, true); + execStat("matching and sorting (n="+String(daeSize(dae))+")"); + + // synchronous features post-phase + dae := SynchronousFeatures.synchronousFeatures(dae); + if Flags.isSet(Flags.OPT_DAE_DUMP) then + BackendDump.dumpBackendDAE(dae, "synchronousFeatures"); + end if; + + if Flags.isSet(Flags.GRAPHML) then + BackendDump.dumpBipartiteGraphDAE(dae, fileNamePrefix); + end if; + + if Flags.isSet(Flags.BLT_DUMP) then + BackendDump.bltdump("bltdump", dae); + end if; + + if Flags.isSet(Flags.EVAL_OUTPUT_ONLY) then + // prepare the equations + dae := BackendDAEOptimize.evaluateOutputsOnly(dae); + end if; + + // generate system for initialization + (outInitDAE, _, outRemovedInitialEquationLst, globalKnownVars) := Initialization.solveInitialSystem(dae); + + // use function tree from initDAE further for simDAE + simDAE := BackendDAEUtil.setFunctionTree(dae, BackendDAEUtil.getFunctions(outInitDAE.shared)); + + // Set updated globalKnownVars + simDAE := setDAEGlobalKnownVars(simDAE, globalKnownVars); + + simDAE := BackendDAEOptimize.addInitialStmtsToAlgorithms(simDAE); + simDAE := Initialization.removeInitializationStuff(simDAE); + + // generate inline solver + outInlineData := SymbolicImplicitSolver.symSolver(simDAE); + + // post-optimization phase + simDAE := postOptimizeDAE(simDAE, postOptModules, matchingAlgorithm, daeHandler); + + // sort the globalKnownVars + simDAE := sortGlobalKnownVarsInDAE(simDAE); + execStat("sort global known variables"); + + // remove unused functions + funcTree := BackendDAEOptimize.copyRecordConstructorAndExternalObjConstructorDestructor(BackendDAEUtil.getFunctions(simDAE.shared)); + funcTree := BackendDAEOptimize.removeUnusedFunctions(outInitDAE.eqs, outInitDAE.shared, outRemovedInitialEquationLst, BackendDAEUtil.getFunctions(simDAE.shared), funcTree); + funcTree := BackendDAEOptimize.removeUnusedFunctions(simDAE.eqs, simDAE.shared, {}, BackendDAEUtil.getFunctions(simDAE.shared), funcTree); + outSimDAE := BackendDAEUtil.setFunctionTree(simDAE, funcTree); + execStat("remove unused functions"); + + if Flags.isSet(Flags.DUMP_INDX_DAE) then + BackendDump.dumpBackendDAE(outSimDAE, "dumpindxdae"); + if Flags.isSet(Flags.ADDITIONAL_GRAPHVIZ_DUMP) then + BackendDump.graphvizBackendDAE(outSimDAE, "dumpindxdae"); + end if; + end if; + if Flags.isSet(Flags.DUMP_TRANSFORMED_MODELICA_MODEL) then + BackendDump.dumpBackendDAEToModelica(outSimDAE, "dumpindxdae"); + end if; + if Flags.isSet(Flags.DUMP_BACKENDDAE_INFO) or Flags.isSet(Flags.DUMP_STATESELECTION_INFO) or Flags.isSet(Flags.DUMP_DISCRETEVARS_INFO) then + BackendDump.dumpCompShort(outSimDAE); + end if; + if Flags.isSet(Flags.DUMP_EQNINORDER) then + BackendDump.dumpEqnsSolved(outSimDAE, "indxdae: eqns in order"); + end if; + if Flags.isSet(Flags.DUMP_LOOPS) then + BackendDump.dumpLoops(outSimDAE); + end if; + checkBackendDAEWithErrorMsg(outSimDAE); + return; + else + setGlobalRoot(Global.stackoverFlowIndex, NONE()); + ErrorExt.rollbackNumCheckpoints(ErrorExt.getNumCheckpoints()-numCheckpoints); + Error.addInternalError("Stack overflow in "+getInstanceName()+"...\n"+stringDelimitList(StackOverflow.readableStacktraceMessages(), "\n"), sourceInfo()); + /* Do not fail or we can loop too much */ + StackOverflow.clearStacktraceMessages(); + end try annotation(__OpenModelica_stackOverflowCheckpoint=true); + fail(); +end getOptimizesDAEModeSystem; + protected function sortGlobalKnownVarsInDAE " author: ptaeuber This function sorts the globalKnownVars" @@ -7442,7 +7567,7 @@ end selectMatchingAlgorithm; // // ============================================================================= -protected function allPreOptimizationModules +public function allPreOptimizationModules "This list contains all back end pre-optimization modules." output list> allPreOptimizationModules = { (UnitCheck.unitChecking, "unitChecking"), @@ -7480,7 +7605,7 @@ protected function allPreOptimizationModules }; end allPreOptimizationModules; -protected function allPostOptimizationModules +public function allPostOptimizationModules "This list contains all back end sim-optimization modules." output list> allPostOptimizationModules = { (BackendDAEUtil.createAliasVarsForOutputStates, "createAliasVarsForOutputStates"), @@ -7488,6 +7613,7 @@ protected function allPostOptimizationModules (DynamicOptimization.simplifyConstraints, "simplifyConstraints"), (CommonSubExpression.wrapFunctionCalls, "wrapFunctionCalls"), (CommonSubExpression.cseBinary, "cseBinary"), + (BackendDAEOptimize.replaceDerCalls, "replaceDerCalls"), (OnRelaxation.relaxSystem, "relaxSystem"), (InlineArrayEquations.inlineArrayEqn, "inlineArrayEqn"), (SymbolicJacobian.constantLinearSystem, "constantLinearSystem"), @@ -7525,7 +7651,10 @@ protected function allPostOptimizationModules (BackendDump.dumpDAE, "dumpDAE"), (XMLDump.dumpDAEXML, "dumpDAEXML"), // This should indeed be at the end - (BackendDAETransform.collapseArrayExpressions, "collapseArrayExpressions") + (BackendDAETransform.collapseArrayExpressions, "collapseArrayExpressions"), + // DAEmode modules + (DAEMode.createDAEmodeBDAE, "createDAEmodeBDAE"), + (SymbolicJacobian.detectSparsePatternDAE, "detectDAEmodeSparsePattern") }; end allPostOptimizationModules; @@ -7585,7 +7714,7 @@ algorithm end if; end deprecatedConfigFlag; -protected function getPreOptModules +public function getPreOptModules input Option> inPreOptModules; output list> outPreOptModules; protected @@ -8464,7 +8593,8 @@ algorithm backendDAEType, {}, ei, - emptyPartitionsInfo() + emptyPartitionsInfo(), + BackendDAE.emptyDAEModeData ); end createEmptyShared; @@ -8636,6 +8766,20 @@ algorithm end match; end setEqSystMatching; +public function setEqSystStateSets + input BackendDAE.EqSystem inSyst; + input BackendDAE.StateSets stateSets; + output BackendDAE.EqSystem outSyst; +algorithm + outSyst := match inSyst + local + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM() + algorithm syst.stateSets := stateSets; + then syst; + end match; +end setEqSystStateSets; + public function setEqSystRemovedEqns input BackendDAE.EqSystem inSyst; input BackendDAE.EquationArray removedEqs; @@ -8758,6 +8902,16 @@ algorithm end match; end setSharedOptimica; +public function collapseOrderedEqs + input BackendDAE.BackendDAE inDAE; + output BackendDAE.EquationArray outEqns; +protected + list eqsLst; +algorithm + eqsLst := List.fold(inDAE.eqs, collapseRemovedEqs1, {}); + outEqns := BackendEquation.listEquation(listAppend(eqsLst, BackendEquation.equationList(inDAE.shared.removedEqs))); +end collapseOrderedEqs; + public function collapseRemovedEqs input BackendDAE.BackendDAE inDAE; output BackendDAE.EquationArray outEqns; diff --git a/Compiler/BackEnd/BackendDump.mo b/Compiler/BackEnd/BackendDump.mo index ffc3547bd09..ad5c54a4997 100644 --- a/Compiler/BackEnd/BackendDump.mo +++ b/Compiler/BackEnd/BackendDump.mo @@ -2481,6 +2481,8 @@ algorithm case BackendDAE.OPT_LOOP_INPUT() then "OPT_LOOP_INPUT"; case BackendDAE.ALG_STATE() then "ALG_STATE"; case BackendDAE.ALG_STATE_OLD() then "ALG_STATE_OLD"; + case BackendDAE.DAE_RESIDUAL_VAR() then "DAE_RESIDUAL_VAR"; + case BackendDAE.DAE_AUX_VAR() then "DAE_AUX_VAR"; end match; end kindString; diff --git a/Compiler/BackEnd/BackendEquation.mo b/Compiler/BackEnd/BackendEquation.mo index 8a5efdc74d8..18f0ab790bd 100644 --- a/Compiler/BackEnd/BackendEquation.mo +++ b/Compiler/BackEnd/BackendEquation.mo @@ -2233,6 +2233,29 @@ algorithm outEqn := BackendDAE.RESIDUAL_EQUATION(e, source, inEqAttr); end generateRESIDUAL_EQUATION1; +public function equationSystemsEqnsLst + input BackendDAE.EqSystems systs; + output list outEqns = {}; +protected + list eqns; + BackendDAE.EquationArray eq; +algorithm + for es in systs loop + BackendDAE.EQSYSTEM(orderedEqs=eq) := es; + eqns := equationList(eq); + outEqns := List.append_reverse(eqns, outEqns); + end for; + outEqns := MetaModelica.Dangerous.listReverseInPlace(outEqns); +end equationSystemsEqnsLst; + +public function getEqnsFromEqSystems " + Extracts the orderedEqs attribute from an equation system." + input BackendDAE.EqSystems inEqSystems; + output BackendDAE.EquationArray outOrderedEqs; +algorithm + outOrderedEqs := listEquation(equationSystemsEqnsLst(inEqSystems)); +end getEqnsFromEqSystems; + public function getEqnsFromEqSystem " Extracts the orderedEqs attribute from an equation system." input BackendDAE.EqSystem inEqSystem; diff --git a/Compiler/BackEnd/BackendVariable.mo b/Compiler/BackEnd/BackendVariable.mo index 69e42c9d7dd..39271f97050 100644 --- a/Compiler/BackEnd/BackendVariable.mo +++ b/Compiler/BackEnd/BackendVariable.mo @@ -44,6 +44,7 @@ protected import Absyn; import Array; import BackendDAEUtil; +import BackendDump; import BaseHashSet; import BaseHashTable; import ComponentReference; @@ -1179,6 +1180,40 @@ algorithm end match; end isRealOptimizeConstraintsVars; +public function isDAEmodeVar +"Return true if variable is a daeMode variable" + input BackendDAE.Var inVar; + output Boolean outBoolean; +algorithm + outBoolean := match (inVar) + case (BackendDAE.VAR(varKind = BackendDAE.DAE_RESIDUAL_VAR())) then true; + case (BackendDAE.VAR(varKind = BackendDAE.DAE_AUX_VAR())) then true; + else false; + end match; +end isDAEmodeVar; + +public function isDAEmodeResVar +"Return true if variable is a daeMode variable" + input BackendDAE.Var inVar; + output Boolean outBoolean; +algorithm + outBoolean := match (inVar) + case (BackendDAE.VAR(varKind = BackendDAE.DAE_RESIDUAL_VAR())) then true; + else false; + end match; +end isDAEmodeResVar; + +public function isDAEmodeAuxVar +"Return true if variable is a daeMode variable" + input BackendDAE.Var inVar; + output Boolean outBoolean; +algorithm + outBoolean := match (inVar) + case (BackendDAE.VAR(varKind = BackendDAE.DAE_AUX_VAR())) then true; + else false; + end match; +end isDAEmodeAuxVar; + public function isRealOptimizeFinalConstraintsVars "Return true if variable is a final constraint(slack variable)" input BackendDAE.Var inVar; @@ -2546,7 +2581,7 @@ algorithm cr_indices := indices[hash_idx]; cr_indices := List.deleteMemberOnTrue(BackendDAE.CREFINDEX(cr, inIndex - 1), cr_indices, removeVar2); arrayUpdate(indices, hash_idx, cr_indices); - outVariables := BackendDAE.VARIABLES(indices, arr, buckets, num_vars); + outVariables := BackendDAE.VARIABLES(indices, arr, buckets, num_vars-1); end removeVar; protected function removeVar2 @@ -3401,6 +3436,31 @@ algorithm end matchcontinue; end traversingVarCrefFinder; +public function collectVarKindVarinVariables + input BackendDAE.Var inVar; + input tuple inVarArrays; + output BackendDAE.Var outVar = inVar; + output tuple outVarArrays = inVarArrays; + partial function checkVarKindFunc + input BackendDAE.Var inVar; + output Boolean outArg; + end checkVarKindFunc; +protected + BackendDAE.Variables vararray; + checkVarKindFunc checkVarKind; +algorithm + (checkVarKind, vararray) := inVarArrays; + outVarArrays := match(inVar) + local + BackendDAE.VarKind varKind; + case (_) guard(checkVarKind(inVar)) algorithm + vararray := BackendVariable.addVar(inVar, vararray); + then (checkVarKind, vararray); + + else outVarArrays; + end match; +end collectVarKindVarinVariables; + public function getAllDiscreteVarFromVariables input BackendDAE.Variables inVariables; output list v_lst; diff --git a/Compiler/BackEnd/CommonSubExpression.mo b/Compiler/BackEnd/CommonSubExpression.mo index 2502ad19a4e..8aa4485b6c9 100644 --- a/Compiler/BackEnd/CommonSubExpression.mo +++ b/Compiler/BackEnd/CommonSubExpression.mo @@ -1591,7 +1591,7 @@ algorithm end matchcontinue; end isCSECref; -protected function isCSEExp +public function isCSEExp "Returns true if the exp is prefixed with '$cse'" input DAE.Exp inExp; output Boolean b; diff --git a/Compiler/BackEnd/DAEMode.mo b/Compiler/BackEnd/DAEMode.mo new file mode 100644 index 00000000000..052ac085c90 --- /dev/null +++ b/Compiler/BackEnd/DAEMode.mo @@ -0,0 +1,322 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2017, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +encapsulated package DAEMode +" file: DAEMode.mo + package: DAEMode + description: This module prepares BackendDAE equations to solve + to pass them directly to a DAE solver. + + Therefor all equations are transformed to residual form: + residualVar = eqRHS - eqLHS + +" +public + +import BackendDAE; + +protected + +import Absyn; +import BackendDAEOptimize; +import BackendDAEUtil; +import BackendDAEFunc; +import BackendDump; +import BackendEquation; +import BackendVariable; +import CommonSubExpression; +import ComponentReference; +import Config; +import DAE; +import ErrorExt; +import ExecStat.execStat; +import Expression; +import Global; +import Initialization; +import StackOverflow; +import Util; + +public function getEqSystemDAEmode "Run the equation system pipeline." + input BackendDAE.BackendDAE inDAE; + input String fileNamePrefix; + input Option> strPreOptModules = NONE(); + input Option strmatchingAlgorithm = NONE(); + input Option strdaeHandler = NONE(); + input Option> strPostOptModules = NONE(); + output BackendDAE.BackendDAE outDAEmode; + output BackendDAE.BackendDAE outInitDAE; + output list outRemovedInitialEquationLst; + protected + BackendDAE.BackendDAE dae, simDAE; + list> preOptModules; + list> postOptModules; + tuple daeHandler; + tuple matchingAlgorithm; + BackendDAE.Variables globalKnownVars; + Integer numCheckpoints; + BackendDAE.EqSystem eqSyst; +algorithm + numCheckpoints:=ErrorExt.getNumCheckpoints(); + try + StackOverflow.clearStacktraceMessages(); + preOptModules := BackendDAEUtil.getPreOptModules(strPreOptModules); + postOptModules := BackendDAEUtil.getPostOptModules(match strPostOptModules case (NONE()) then SOME(getPostOptModulesDAEString()); else strPostOptModules; end match); + matchingAlgorithm := BackendDAEUtil.getMatchingAlgorithm(strmatchingAlgorithm); + Flags.setConfigString(Flags.INDEX_REDUCTION_METHOD, "dummyDerivatives"); + daeHandler := BackendDAEUtil.getIndexReductionMethod(strdaeHandler); + + if Flags.isSet(Flags.DUMP_DAE_LOW) then + BackendDump.dumpBackendDAE(inDAE, "dumpdaelow"); + if Flags.isSet(Flags.ADDITIONAL_GRAPHVIZ_DUMP) then + BackendDump.graphvizIncidenceMatrix(inDAE, "dumpdaelow"); + end if; + end if; + + // pre-optimization phase + dae := BackendDAEUtil.preOptimizeDAE(inDAE, preOptModules); + + execStat("pre-optimization done (n="+String(BackendDAEUtil.daeSize(dae))+")"); + // transformation phase (matching and sorting using index reduction method) + dae := BackendDAEUtil.causalizeDAE(dae, NONE(), matchingAlgorithm, daeHandler, true); + execStat("matching and sorting (n="+String(BackendDAEUtil.daeSize(dae))+")"); + + if Flags.isSet(Flags.GRAPHML) then + BackendDump.dumpBipartiteGraphDAE(dae, fileNamePrefix); + end if; + + if Flags.isSet(Flags.BLT_DUMP) then + BackendDump.bltdump("bltdump", dae); + end if; + + // generate system for initialization + (outInitDAE, _, outRemovedInitialEquationLst, globalKnownVars) := Initialization.solveInitialSystem(dae); + + // use function tree from initDAE further for simDAE + simDAE := BackendDAEUtil.setFunctionTree(dae, BackendDAEUtil.getFunctions(outInitDAE.shared)); + + // Set updated globalKnownVars + simDAE := BackendDAEUtil.setDAEGlobalKnownVars(simDAE, globalKnownVars); + simDAE := BackendDAEOptimize.addInitialStmtsToAlgorithms(simDAE); + simDAE := Initialization.removeInitializationStuff(simDAE); + + // post-optimization phase + // use preOpt instead + simDAE := BackendDAEUtil.postOptimizeDAE(simDAE, postOptModules, matchingAlgorithm, daeHandler); + + // debug dump + if Flags.isSet(Flags.DUMP_INDX_DAE) then + BackendDump.dumpBackendDAE(simDAE, "dumpindxdae"); + end if; + + outDAEmode := simDAE; + return; + else + setGlobalRoot(Global.stackoverFlowIndex, NONE()); + ErrorExt.rollbackNumCheckpoints(ErrorExt.getNumCheckpoints()-numCheckpoints); + Error.addInternalError("Stack overflow in "+getInstanceName()+"...\n"+stringDelimitList(StackOverflow.readableStacktraceMessages(), "\n"), sourceInfo()); + /* Do not fail or we can loop too much */ + StackOverflow.clearStacktraceMessages(); + end try annotation(__OpenModelica_stackOverflowCheckpoint=true); + fail(); +end getEqSystemDAEmode; + + +// ============================================================================= +// section for postOptModule >>calculateStateSetsJacobians<< +// +// ============================================================================= + +protected +type TraverseEqnAryFold = tuple ; + +public function createDAEmodeBDAE +" This modules creates a BDAE with residual Variables." + input BackendDAE.BackendDAE inDAE; + output BackendDAE.BackendDAE outDAE; +algorithm + outDAE := BackendDAEUtil.mapEqSystem(inDAE, createDAEmodeEqSystem); +end createDAEmodeBDAE; + + +protected function createDAEmodeEqSystem +"The main to create equations by adding auxiliary variables + and auxiliary equations of the form $auxExp = rhs, $resVar = $auxExp - lhs" + input output BackendDAE.EqSystem syst; + input output BackendDAE.Shared shared; +protected + TraverseEqnAryFold travArgs; + BackendDAE.BackendDAEModeData extraArgs; + BackendDAE.EquationArray tmp; + BackendDAE.Variables vars; + BackendDAE.EqSystem retSystem; + constant Boolean debug = false; +algorithm + extraArgs := BackendDAE.BDAE_MODE_DATA(shared.daeModeData.numAuxVars,{},shared.daeModeData.numResVars,{},shared.daeModeData.numAuxEqns,{},shared.daeModeData.numResEqns,{}); + travArgs := (extraArgs, syst.orderedVars); + if debug then BackendDump.printEqSystem(syst); end if; + // for every equation create corresponding residiual variable(s) + travArgs := BackendEquation.traverseEquationArray(syst.orderedEqs, + traverserEqnAryAuxRes, travArgs); + (extraArgs, vars) := travArgs; + syst.orderedVars := vars; + + // push ordered variables to known vars + shared.localKnownVars := BackendVariable.addVariables(syst.orderedVars, shared.localKnownVars); + + // create residual system + extraArgs.resVars := listAppend(extraArgs.resVars, extraArgs.auxVars); + retSystem := BackendDAEUtil.createEqSystem(BackendVariable.listVar(extraArgs.resVars)); + + extraArgs.resEqns := listReverse(extraArgs.resEqns); + extraArgs.resEqns := listAppend(listReverse(extraArgs.auxEqns),extraArgs.resEqns); + retSystem := BackendDAEUtil.setEqSystEqs(retSystem, BackendEquation.listEquation(extraArgs.resEqns)); + + retSystem := BackendDAEUtil.setEqSystStateSets(retSystem, syst.stateSets); + syst := retSystem; + shared.daeModeData := extraArgs; + if debug then BackendDump.printEqSystem(syst); end if; + +end createDAEmodeEqSystem; + +protected function traverserEqnAryAuxRes +"This function prepares an equation system for + the dae mode by dividing the equations into + aux equations and residual equations. + + " + input output BackendDAE.Equation orgEquation; + input output TraverseEqnAryFold extraArgs; +algorithm + (extraArgs) := + matchcontinue (orgEquation) + local + list newResEqns; + list newResVars; + BackendDAE.Variables orderedVars; + BackendDAE.Var dummyVar; + BackendDAE.Equation eq; + Integer newnumResVars; + DAE.Exp exp; + BackendDAE.BackendDAEModeData travArgs; + DAE.ComponentRef cref; + String str; + + case (eq as BackendDAE.EQUATION(exp=exp)) guard( CommonSubExpression.isCSEExp(exp)) + equation + (travArgs, orderedVars) = extraArgs; + cref = Expression.expCref(exp); + (newResVars,_) = BackendVariable.getVar(cref, orderedVars); + newResVars = list(BackendVariable.setVarKind(v, BackendDAE.DAE_AUX_VAR()) for v in newResVars); + travArgs.auxVars = listAppend(newResVars, travArgs.auxVars); + travArgs.auxEqns = listAppend({eq}, travArgs.auxEqns); + orderedVars = BackendVariable.removeCref(cref, orderedVars); + extraArgs = (travArgs, orderedVars); + then + (extraArgs); + + case (eq as BackendDAE.EQUATION()) + equation + (travArgs, orderedVars) = extraArgs; + newResEqns = BackendEquation.equationToScalarResidualForm(eq); + dummyVar = BackendVariable.makeVar(DAE.emptyCref); + dummyVar = BackendVariable.setVarKind(dummyVar, BackendDAE.DAE_RESIDUAL_VAR()); + (newResEqns, newResVars, newnumResVars) = BackendEquation.convertResidualsIntoSolvedEquations(newResEqns, + "$DAEres", dummyVar, travArgs.numResVars); + travArgs.numResVars = newnumResVars; + travArgs.resVars = listAppend(newResVars, travArgs.resVars); + travArgs.resEqns = listAppend(newResEqns, travArgs.resEqns); + extraArgs = (travArgs, orderedVars); + then + (extraArgs); + + case (eq as BackendDAE.SOLVED_EQUATION()) + equation + (travArgs, orderedVars) = extraArgs; + newResEqns = BackendEquation.equationToScalarResidualForm(eq); + dummyVar = BackendVariable.makeVar(DAE.emptyCref); + dummyVar = BackendVariable.setVarKind(dummyVar, BackendDAE.DAE_RESIDUAL_VAR()); + (newResEqns, newResVars, newnumResVars) = BackendEquation.convertResidualsIntoSolvedEquations(newResEqns, + "$DAEres", dummyVar, travArgs.numResVars); + travArgs.numResVars = newnumResVars; + travArgs.resVars = listAppend(newResVars, travArgs.resVars); + travArgs.resEqns = listAppend(newResEqns, travArgs.resEqns); + extraArgs = (travArgs, orderedVars); + then + (extraArgs); + + case (eq as BackendDAE.ARRAY_EQUATION()) + equation + (travArgs, orderedVars) = extraArgs; + newResEqns = BackendEquation.equationToScalarResidualForm(eq); + dummyVar = BackendVariable.makeVar(DAE.emptyCref); + dummyVar = BackendVariable.setVarKind(dummyVar, BackendDAE.DAE_RESIDUAL_VAR()); + (newResEqns, newResVars, newnumResVars) = BackendEquation.convertResidualsIntoSolvedEquations(newResEqns, + "$DAEres", dummyVar, travArgs.numResVars); + travArgs.numResVars = newnumResVars; + travArgs.resVars = listAppend(listReverse(newResVars), travArgs.resVars); + travArgs.resEqns = listAppend(newResEqns, travArgs.resEqns); + extraArgs = (travArgs, orderedVars); + then + (extraArgs); + + case (eq as BackendDAE.COMPLEX_EQUATION()) + equation + (travArgs, orderedVars) = extraArgs; + newResEqns = BackendEquation.equationToScalarResidualForm(eq); + dummyVar = BackendVariable.makeVar(DAE.emptyCref); + dummyVar = BackendVariable.setVarKind(dummyVar, BackendDAE.DAE_RESIDUAL_VAR()); + (newResEqns, newResVars, newnumResVars) = BackendEquation.convertResidualsIntoSolvedEquations(newResEqns, + "$DAEres", dummyVar, travArgs.numResVars); + travArgs.numResVars = newnumResVars; + travArgs.resVars = listAppend(newResVars, travArgs.resVars); + travArgs.resEqns = listAppend(newResEqns, travArgs.resEqns); + extraArgs = (travArgs, orderedVars); + then + (extraArgs); + + else equation + str = BackendDump.equationString(orgEquation); + Error.addInternalError("DAEMode.traverserEqnAryAuxRes failed on equation:\n" + str + "\n", sourceInfo()); + then fail(); + end matchcontinue; +end traverserEqnAryAuxRes; + +/* +get config function +*/ +protected function getPostOptModulesDAEString + output list strpostOptModules; +algorithm + strpostOptModules := Config.getPostOptModulesDAE(); +end getPostOptModulesDAEString; + +annotation(__OpenModelica_Interface="backend"); +end DAEMode; diff --git a/Compiler/BackEnd/SymbolicJacobian.mo b/Compiler/BackEnd/SymbolicJacobian.mo index 368ec2fecdf..e4caf09de7c 100644 --- a/Compiler/BackEnd/SymbolicJacobian.mo +++ b/Compiler/BackEnd/SymbolicJacobian.mo @@ -174,6 +174,64 @@ algorithm end try; end detectSparsePatternODE; + + +// ============================================================================= +// section for postOptModule >>detectSparsePatternDAE<< +// +// Generate sparse pattern +// ============================================================================= +public function detectSparsePatternDAE + input BackendDAE.BackendDAE inBackendDAE; + output BackendDAE.BackendDAE outBackendDAE; +protected + BackendDAE.BackendDAE DAE; + BackendDAE.EqSystems eqs; + BackendDAE.Shared shared; + BackendDAE.SparseColoring coloredCols; + BackendDAE.SparsePattern sparsePattern; + list inDepVars; + list depVars; + BackendDAE.Var dummyVar; + BackendDAE.Variables v, resVars; + BackendDAE.Variables emptyVars = BackendVariable.emptyVars(); + constant Boolean debug = false; +algorithm + try + if debug then execStat("detectSparsePatternDAE -> start "); end if; + BackendDAE.DAE(eqs = eqs) := inBackendDAE; + + // prepare a DAE + DAE := BackendDAEUtil.copyBackendDAE(inBackendDAE); + if debug then execStat("detectSparsePatternDAE -> copy dae "); end if; + DAE := BackendDAEOptimize.collapseIndependentBlocks(DAE); + if debug then execStat("detectSparsePatternDAE -> collapse blocks "); end if; + DAE := BackendDAEUtil.transformBackendDAE(DAE, SOME((BackendDAE.NO_INDEX_REDUCTION(), BackendDAE.EXACT())), NONE(), NONE()); + if debug then execStat("detectSparsePatternDAE -> transform backend dae "); end if; + + // get states for DAE + BackendDAE.DAE(eqs = {BackendDAE.EQSYSTEM(orderedVars = v)}, shared=shared) := DAE; + ((_, resVars)) := BackendVariable.traverseBackendDAEVars(v, BackendVariable.collectVarKindVarinVariables, (BackendVariable.isDAEmodeResVar, emptyVars)); + depVars := BackendVariable.varList(resVars); + + inDepVars := BackendVariable.varList(shared.localKnownVars); + + if debug then execStat("detectSparsePatternDAE -> get all vars "); end if; + + // generate sparse pattern + (sparsePattern, coloredCols) := generateSparsePattern(DAE, inDepVars, depVars); + if debug then execStat("detectSparsePatternDAE -> generateSparsePattern "); end if; + shared := addBackendDAESharedJacobianSparsePattern(sparsePattern, coloredCols, BackendDAE.SymbolicJacobianAIndex, shared); + if debug then execStat("detectSparsePatternDAE -> addBackendDAESharedJacobianSparsePattern "); end if; + + outBackendDAE := BackendDAE.DAE(eqs, shared); + else + // skip this optimization module + Error.addCompilerWarning("The optimization module detectJacobianSparsePattern failed. This module will be skipped and the transformation process continued."); + outBackendDAE := inBackendDAE; + end try; +end detectSparsePatternDAE; + // ============================================================================= // section for postOptModule >>generateSymbolicJacobianPast<< // diff --git a/Compiler/Script/CevalScriptBackend.mo b/Compiler/Script/CevalScriptBackend.mo index 35fd2a25b25..40a10f70db2 100644 --- a/Compiler/Script/CevalScriptBackend.mo +++ b/Compiler/Script/CevalScriptBackend.mo @@ -1282,7 +1282,7 @@ algorithm case (cache,env,"translateModel",vals as {Values.CODE(Absyn.C_TYPENAME(className)),_,_,_,_,_,Values.STRING(filenameprefix),_,_,_,_,_},_) equation (cache,simSettings) = calculateSimulationSettings(cache,env,vals,msg); - (b,cache,_,_,_,_) = translateModel(cache, env, className, filenameprefix, true, SOME(simSettings)); + (b,cache,_,_,_) = translateModel(cache, env, className, filenameprefix, true, SOME(simSettings)); then (cache,Values.BOOL(b)); @@ -3110,17 +3110,15 @@ protected function translateModel " author: x02lucpo input Option inSimSettingsOpt; output Boolean success; output FCore.Cache outCache; - output BackendDAE.BackendDAE outBackendDAE; output list outStringLst; output String outFileDir; output list> resultValues; algorithm - (outCache,outBackendDAE,outStringLst,outFileDir,resultValues):= + (outCache,outStringLst,outFileDir,resultValues):= match (inCache,inEnv,className,inFileNamePrefix,addDummy,inSimSettingsOpt) local FCore.Cache cache; FCore.Graph env; - BackendDAE.BackendDAE indexed_dlow; list libs; String file_dir, fileNamePrefix; Absyn.Program p; @@ -3132,8 +3130,8 @@ algorithm case (cache,env,_,fileNamePrefix,_,_) algorithm if Config.ignoreCommandLineOptionsAnnotation() then - (success, cache, indexed_dlow, libs, file_dir, resultValues) := - SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.NORMAL(),cache,env,className,fileNamePrefix,addDummy,inSimSettingsOpt); + (success, cache, libs, file_dir, resultValues) := + callTranslateModel(cache,env,className,fileNamePrefix,inSimSettingsOpt); else // read the __OpenModelica_commandLineOptions Absyn.STRING(commandLineOptions) := Interactive.getNamedAnnotation(className, SymbolTable.getAbsyn(), Absyn.IDENT("__OpenModelica_commandLineOptions"), SOME(Absyn.STRING("")), Interactive.getAnnotationExp); @@ -3147,8 +3145,8 @@ algorithm _ := Flags.readArgs(args); end if; - (success, cache, indexed_dlow, libs, file_dir, resultValues) := - SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.NORMAL(),cache,env,className,fileNamePrefix,addDummy,inSimSettingsOpt); + (success, cache, libs, file_dir, resultValues) := + callTranslateModel(cache,env,className,fileNamePrefix,inSimSettingsOpt); // reset to the original flags Flags.saveFlags(flags); else @@ -3157,7 +3155,7 @@ algorithm end try; end if; then - (cache,indexed_dlow,libs,file_dir,resultValues); + (cache,libs,file_dir,resultValues); end match; end translateModel; @@ -3177,7 +3175,7 @@ protected function translateLabeledModel " author: Fatima output String outFileDir; output list> resultValues; algorithm - (outCache,outBackendDAE,outStringLst,outFileDir,resultValues):= + (outCache,outStringLst,outFileDir,resultValues):= match (inCache,inEnv,className,inFileNamePrefix,addDummy,inSimSettingsOpt,inLabelstoCancel) local FCore.Cache cache; @@ -3196,7 +3194,7 @@ algorithm algorithm if Config.ignoreCommandLineOptionsAnnotation() then - (true, cache, indexed_dlow, libs, file_dir, resultValues) := + (true, cache, libs, file_dir, resultValues) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.NORMAL(),cache,env,className,fileNamePrefix,addDummy,inSimSettingsOpt,Absyn.FUNCTIONARGS({},argNames =labelstoCancel)); else // read the __OpenModelica_commandLineOptions @@ -3211,7 +3209,7 @@ algorithm _ := Flags.readArgs(args); end if; - (true, cache, indexed_dlow, libs, file_dir, resultValues) := + (true, cache, libs, file_dir, resultValues) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.NORMAL(),cache,env,className,fileNamePrefix,addDummy,inSimSettingsOpt,Absyn.FUNCTIONARGS({},argNames =labelstoCancel)); // reset to the original flags Flags.saveFlags(flags); @@ -3221,11 +3219,38 @@ algorithm end try; end if; then - (cache,indexed_dlow,libs,file_dir,resultValues); + (cache,libs,file_dir,resultValues); end match; end translateLabeledModel; +protected function callTranslateModel +"Call the main translate function. This function + distinguish between the modes. Now between DAEMode and ODEmode. + The appropriate function create model code and writes also a makefile" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className "path for the model"; + input String inFileNamePrefix; + input Option inSimSettingsOpt; + output Boolean success; + output FCore.Cache outCache; + output list outStringLst; + output String outFileDir; + output list> resultValues; +algorithm + if Flags.getConfigEnum(Flags.DAE_MODE) > 3 then + (outCache, outStringLst, outFileDir, resultValues) := + SimCodeMain.translateModelDAEMode(inCache,inEnv,className,inFileNamePrefix, + inSimSettingsOpt,Absyn.FUNCTIONARGS({},{})); + success := true; + else + (success, outCache, outStringLst, outFileDir, resultValues) := + SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.NORMAL(),inCache,inEnv, + className,inFileNamePrefix,true,inSimSettingsOpt,Absyn.FUNCTIONARGS({},{})); + end if; +end callTranslateModel; + protected function configureFMU input String platform; input String fmutmp; @@ -3352,7 +3377,7 @@ algorithm simSettings := convertSimulationOptionsToSimCode(defaulSimOpt); Flags.setConfigBool(Flags.BUILDING_FMU, true); try - (success, cache, _, libs,_, _) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.FMU(FMUVersion, FMUType, fmuTargetName), cache, inEnv, className, filenameprefix, addDummy, SOME(simSettings)); + (success, cache, libs,_, _) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.FMU(FMUVersion, FMUType, fmuTargetName), cache, inEnv, className, filenameprefix, addDummy, SOME(simSettings)); true := success; outValue := Values.STRING((if not Config.getRunningTestsuite() then System.pwd() + System.pathDelimiter() else "") + fmuTargetName + ".fmu"); else @@ -4800,7 +4825,7 @@ algorithm SimCode.SIMULATION_SETTINGS(method = method_str, outputFormat = outputFormat_str) := simSettings; - (success,cache,_,libs,file_dir,resultValues) := translateModel(cache,env, classname, filenameprefix,true, SOME(simSettings)); + (success,cache,libs,file_dir,resultValues) := translateModel(cache,env, classname, filenameprefix,true, SOME(simSettings)); //cname_str = Absyn.pathString(classname); //SimCodeUtil.generateInitData(indexed_dlow_1, classname, filenameprefix, init_filename, // starttime_r, stoptime_r, interval_r, tolerance_r, method_str,options_str,outputFormat_str); diff --git a/Compiler/SimCode/SimCode.mo b/Compiler/SimCode/SimCode.mo index 4977f2f6617..a67c0f6e6c8 100644 --- a/Compiler/SimCode/SimCode.mo +++ b/Compiler/SimCode/SimCode.mo @@ -284,7 +284,8 @@ uniontype DaeModeData list> daeEquations "daeModel residuals equations"; Option sparsityPattern "contains the sparsity pattern for the daeMode"; list residualVars; // variable used to calculate residuals of a DAE form, they are real - list algebraicDAEVars; // variable used to calculate residuals of a DAE form, they are real + list algebraicVars; + list auxiliaryVars; DaeModeConfig modeCreated; // indicates the mode in which end DAEMODEDATA; end DaeModeData; diff --git a/Compiler/SimCode/SimCodeMain.mo b/Compiler/SimCode/SimCodeMain.mo index 441b4c5a83e..608cfe17f4f 100644 --- a/Compiler/SimCode/SimCodeMain.mo +++ b/Compiler/SimCode/SimCodeMain.mo @@ -56,7 +56,10 @@ import SimCode; protected import AvlSetString; import BackendDAECreate; +import BackendDAEOptimize; import BackendDump; +import BackendEquation; +import BackendVariable; import Builtin; import ClockIndexes; import CevalScriptBackend; @@ -74,6 +77,7 @@ import CodegenXML; import CodegenJava; import CodegenJS; import Config; +import DAEMode; import DAEUtil; import Debug; import Error; @@ -82,12 +86,16 @@ import ExecStat; import Flags; import FMI; import GC; +import HashTable; +import HashTableCrIListArray; +import HashTableCrILst; import HpcOmSimCodeMain; import HpcOmTaskGraph; import SerializeModelInfo; import TaskSystemDump; import SerializeInitXML; import Serializer; +import SimCodeDump; import SimCodeUtil; import StackOverflow; import StringUtil; @@ -167,13 +175,12 @@ algorithm a_cref := Absyn.pathToCref(className); fileDir := CevalScriptBackend.getFileDir(a_cref, p); (libs,libPaths,includes, includeDirs, recordDecls, functions, literals) := - SimCodeUtil.createFunctions(p, inBackendDAE); + SimCodeUtil.createFunctions(p, inBackendDAE.shared.functionTree); simCode := createSimCode(inBackendDAE, inInitDAE, inInitDAE_lambda0, NONE(), inRemovedInitialEquationLst, className, filenamePrefix, fileDir, functions, includes, includeDirs, libs, libPaths, p, simSettings, recordDecls, literals, Absyn.FUNCTIONARGS({},{}), isFMU=true, FMUVersion=FMUVersion, fmuTargetName=fmuTargetName, inFMIDer=inFMIDer); - timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); ExecStat.execStat("SimCode"); @@ -214,7 +221,7 @@ algorithm a_cref := Absyn.pathToCref(className); fileDir := CevalScriptBackend.getFileDir(a_cref, p); (libs, libPaths, includes, includeDirs, recordDecls, functions, literals) := - SimCodeUtil.createFunctions(p, inBackendDAE); + SimCodeUtil.createFunctions(p, inBackendDAE.shared.functionTree); (simCode,_) := SimCodeUtil.createSimCode(inBackendDAE, inInitDAE, inInitDAE_lambda0, NONE(), inRemovedInitialEquationLst, className, filenamePrefix, fileDir, functions, includes, includeDirs, libs,libPaths, p, simSettingsOpt, recordDecls, literals,Absyn.FUNCTIONARGS({},{})); timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); @@ -263,7 +270,7 @@ algorithm a_cref := Absyn.pathToCref(className); fileDir := CevalScriptBackend.getFileDir(a_cref, p); - (libs, libPaths, includes, includeDirs, recordDecls, functions, literals) := SimCodeUtil.createFunctions(p, inBackendDAE); + (libs, libPaths, includes, includeDirs, recordDecls, functions, literals) := SimCodeUtil.createFunctions(p, inBackendDAE.shared.functionTree); simCode := createSimCode(inBackendDAE, inInitDAE, inInitDAE_lambda0, inInlineData, inRemovedInitialEquationLst, className, filenamePrefix, fileDir, functions, includes, includeDirs, libs,libPaths, p, simSettingsOpt, recordDecls, literals, args); timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); ExecStat.execStat("SimCode"); @@ -730,7 +737,6 @@ public function translateModel " input Boolean addDummy "if true, add a dummy state"; input Option inSimSettingsOpt; input Absyn.FunctionArgs args=Absyn.emptyFunctionArgs "labels for remove terms"; - output BackendDAE.BackendDAE outBackendDAE; output list outStringLst; output String outFileDir; output list> resultValues; @@ -741,7 +747,7 @@ protected State state = State.frontend; algorithm Flags.setConfigBool(Flags.BUILDING_MODEL, true); - (success, outBackendDAE, outStringLst, outFileDir) := + (success, outStringLst, outFileDir) := matchcontinue (inEnv, className, inFileNamePrefix, addDummy, inSimSettingsOpt, args) local String filenameprefix, file_dir, resstr, description; @@ -826,7 +832,6 @@ algorithm else fmiDer := {}; end if; - timeBackend := System.realtimeTock(ClockIndexes.RT_CLOCK_BACKEND); state := State.simcode; @@ -855,7 +860,7 @@ algorithm Error.addInternalError("Unknown translateModel kind: " + anyString(kind), sourceInfo()); then fail(); end match; - then (true, dlow, libs, file_dir); + then (true, libs, file_dir); else algorithm @@ -882,8 +887,7 @@ algorithm else timeTemplates := System.realtimeTock(ClockIndexes.RT_CLOCK_TEMPLATES); end if; - shared := BackendDAEUtil.createEmptyShared(BackendDAE.BackendDAEType.SIMULATION(), BackendDAE.EXTRA_INFO("",""), cache, inEnv); - then (false, BackendDAE.DAE({}, shared), {}, ""); + then (false, {}, ""); end matchcontinue; if generateFunctions then Flags.set(Flags.GEN, true); @@ -895,6 +899,399 @@ algorithm Flags.setConfigBool(Flags.BUILDING_MODEL, false); end translateModel; +public function translateModelDAEMode +" Entry point to translate a Modelica model for simulation in DAE mode + Called from CevalScriptBackend" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className "path for the model"; + input String inFileNamePrefix; + input Option inSimSettingsOpt; + input Absyn.FunctionArgs args "labels for remove terms"; + output FCore.Cache outCache; + output list outStringLst; + output String outFileDir; + output list> resultValues; +protected + Boolean generateFunctions = false; +algorithm + (outStringLst, outFileDir, resultValues) := + matchcontinue (inCache, inEnv, className, inFileNamePrefix, inSimSettingsOpt, args) + local + String filenameprefix = inFileNamePrefix; + String file_dir, resstr, description; + DAE.DAElist dae; + FCore.Graph graph; + BackendDAE.BackendDAE dlow, bdae; + list libs; + Absyn.Program p; + //DAE.Exp fileprefix; + FCore.Cache cache; + Real timeSimCode, timeTemplates, timeBackend, timeFrontend; + BackendDAE.BackendDAE initDAE; + list removedInitialEquationLst; + Real fsize; + Absyn.ComponentRef classNameCref; + + case (_, _, _, _, _, _) algorithm + // calculate stuff that we need to create SimCode data structure + System.realtimeTick(ClockIndexes.RT_CLOCK_FRONTEND); + ExecStat.execStatReset(); + (outCache, graph, SOME(dae)) := CevalScriptBackend.runFrontEnd(inCache, inEnv, className, false); + ExecStat.execStat("FrontEnd"); + + if Flags.isSet(Flags.SERIALIZED_SIZE) then + serializeNotify(dae, filenameprefix, "dae"); + serializeNotify(graph, filenameprefix, "graph"); + serializeNotify(outCache, filenameprefix, "cache"); + ExecStat.execStat("Serialize FrontEnd"); + end if; + + timeFrontend := System.realtimeTock(ClockIndexes.RT_CLOCK_FRONTEND); + + System.realtimeTick(ClockIndexes.RT_CLOCK_BACKEND); + dae := DAEUtil.transformationsBeforeBackend(outCache, graph, dae); + ExecStat.execStat("Transformations before backend"); + + if Flags.isSet(Flags.SERIALIZED_SIZE) then + serializeNotify(dae, filenameprefix, "dae2"); + ExecStat.execStat("Serialize DAE (2)"); + end if; + + generateFunctions := Flags.set(Flags.GEN, false); + // We should not need to lookup constants and classes in the backend, + // so let's free up the old graph and just make it the initial environment. + if not Flags.isSet(Flags.BACKEND_KEEP_ENV_GRAPH) then + (outCache,graph) := Builtin.initialGraph(outCache); + end if; + + description := DAEUtil.daeDescription(dae); + dlow := BackendDAECreate.lower(dae, outCache, graph, BackendDAE.EXTRA_INFO(description,filenameprefix)); + + GC.free(dae); + + if Flags.isSet(Flags.SERIALIZED_SIZE) then + serializeNotify(dlow, filenameprefix, "dlow"); + ExecStat.execStat("Serialize dlow"); + end if; + + //BackendDump.printBackendDAE(dlow); + (bdae, initDAE, removedInitialEquationLst) := DAEMode.getEqSystemDAEmode(dlow,inFileNamePrefix); + ExecStat.execStat("Backend"); + + timeBackend := System.realtimeTock(ClockIndexes.RT_CLOCK_BACKEND); + + if Flags.isSet(Flags.SERIALIZED_SIZE) then + serializeNotify(bdae, filenameprefix, "simDAE"); + serializeNotify(initDAE, filenameprefix, "initDAE"); + serializeNotify(removedInitialEquationLst, filenameprefix, "removedInitialEquationLst"); + ExecStat.execStat("Serialize solved system"); + end if; + + (libs, file_dir, timeSimCode, timeTemplates) := generateModelCodeDAE(bdae, initDAE, removedInitialEquationLst, SymbolTable.getAbsyn(), className, filenameprefix, inSimSettingsOpt, args); + timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); + timeTemplates := System.realtimeTock(ClockIndexes.RT_CLOCK_TEMPLATES); + + resultValues := {("timeTemplates", Values.REAL(timeTemplates)), + ("timeSimCode", Values.REAL(timeSimCode)), + ("timeBackend", Values.REAL(timeBackend)), + ("timeFrontend", Values.REAL(timeFrontend))}; + + + + then (libs, file_dir, resultValues); + + else equation + if generateFunctions then + Flags.set(Flags.GEN, true); + end if; + true = Flags.isSet(Flags.FAILTRACE); + resstr = Absyn.pathStringNoQual(className); + resstr = stringAppendList({"SimCode DAEmode: The model ", resstr, " could not be translated"}); + Error.addMessage(Error.INTERNAL_ERROR, {resstr}); + then fail(); + end matchcontinue; + if generateFunctions then + Flags.set(Flags.GEN, true); + end if; +end translateModelDAEMode; + +protected function generateModelCodeDAE +" Generates code for a model by creating a SimCode structure for the DAEmode + and call the template target generator. " + input BackendDAE.BackendDAE inBackendDAE; + input BackendDAE.BackendDAE inInitDAE; + input list inRemovedInitialEquationLst; + input Absyn.Program p; + input Absyn.Path className; + input String filenamePrefix; + input Option simSettingsOpt; + input Absyn.FunctionArgs args; + output list libs; + output String fileDir; + output Real timeSimCode; + output Real timeTemplates; +protected + constant Boolean debug = false; + list includes, includeDirs,libPaths; + list functions; + SimCode.SimCode simCode; + list recordDecls; + Absyn.ComponentRef a_cref; + tuple> literals; + list lits; + list> program; + Integer numCheckpoints; + list tempVars = {}; + + SimCode.ModelInfo modelInfo; + SimCode.ExtObjInfo extObjInfo; + SimCode.HashTableCrefToSimVar crefToSimVarHT; + SimCodeFunction.MakefileParams makefileParams; + list>> delayedExps; + Integer maxDelayedExpIndex; + Integer uniqueEqIndex = 1; + Integer numberofEqns, numStateSets, numberofLinearSys, numberofNonLinearSys, + numberofMixedSys, numberOfJacobians, numberofFixedParameters; + + list discreteModelVars; + list timeEvents; + BackendDAE.ZeroCrossingSet zeroCrossingsSet, sampleZCSet; + DoubleEndedList de_relations; + list zeroCrossings, sampleZC, relations; + + BackendDAE.Variables daeVars, resVars, algVars, auxVars; + list varsLst; + list eqnsLst; + BackendDAE.EquationArray daeEqns; + BackendDAE.Variables localSharedAlgVars; + Option daeModeSP; + Option daeModeData; + SimCode.DaeModeConfig daeModeConf; + list daeEquations; + list residualVars, algebraicVars, auxiliaryVars; + list stateSets; + + tuple, BackendDAE.SparsePattern, BackendDAE.SparseColoring> daeModeJac; + SimCode.JacobianMatrix symDAESparsPattern; + list symJacs, SymbolicJacs, SymbolicJacsNLS, SymbolicJacsTemp, SymbolicJacsStateSelect; + list initialEquations, removedInitialEquations, jacobianEquations; + list jacobianSimvars, seedVars; + list startValueEquations; // --> updateBoundStartValues + list maxValueEquations; // --> updateBoundMaxValues + list minValueEquations; // --> updateBoundMinValues + list nominalValueEquations; // --> updateBoundNominalValues + list parameterEquations; // --> updateBoundParameters +algorithm + numCheckpoints:=ErrorExt.getNumCheckpoints(); + try + StackOverflow.clearStacktraceMessages(); + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMCODE); + + // +++ create SimCode stuff +++ + // create SimCode functions + a_cref := Absyn.pathToCref(className); + fileDir := CevalScriptBackend.getFileDir(a_cref, p); + (libs, libPaths, includes, includeDirs, recordDecls, functions, literals) := SimCodeUtil.createFunctions(p, inBackendDAE.shared.functionTree); + + // create external objects + extObjInfo := SimCodeUtil.createExtObjInfo(inBackendDAE.shared); + // create make file params + makefileParams := SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, false, false); + //create delay exps + (delayedExps, maxDelayedExpIndex) := SimCodeUtil.extractDelayedExpressions(inBackendDAE); + + // created event suff e.g. zeroCrossings, samples, ... + timeEvents := inBackendDAE.shared.eventInfo.timeEvents; + (zeroCrossings,relations,sampleZC) := match inBackendDAE.shared.eventInfo + case BackendDAE.EVENT_INFO(zeroCrossings=zeroCrossingsSet, relations=de_relations, samples=sampleZCSet) + then (ZeroCrossings.toList(zeroCrossingsSet), DoubleEndedList.toListNoCopyNoClear(de_relations), ZeroCrossings.toList(sampleZCSet)); + end match; + + // initialization stuff + // ******************** + + // generate equations for initDAE + (initialEquations, uniqueEqIndex, tempVars) := SimCodeUtil.createInitialEquations(inInitDAE, uniqueEqIndex, tempVars); + initialEquations := listReverse(initialEquations); + + // generate equations for removed initial equations + (removedInitialEquations, uniqueEqIndex, tempVars) := SimCodeUtil.createNonlinearResidualEquations(inRemovedInitialEquationLst, uniqueEqIndex, tempVars); + removedInitialEquations := listReverse(removedInitialEquations); + + ExecStat.execStat("simCode: created initialization part"); + + // create parameter equations + ((uniqueEqIndex, startValueEquations, _)) := BackendDAEUtil.foldEqSystem(inBackendDAE, SimCodeUtil.createStartValueEquations, (uniqueEqIndex, {}, inBackendDAE.shared.globalKnownVars)); + if debug then ExecStat.execStat("simCode: createStartValueEquations"); end if; + ((uniqueEqIndex, nominalValueEquations)) := BackendDAEUtil.foldEqSystem(inBackendDAE, SimCodeUtil.createNominalValueEquations, (uniqueEqIndex, {})); + if debug then ExecStat.execStat("simCode: createNominalValueEquations"); end if; + ((uniqueEqIndex, minValueEquations)) := BackendDAEUtil.foldEqSystem(inBackendDAE, SimCodeUtil.createMinValueEquations, (uniqueEqIndex, {})); + if debug then ExecStat.execStat("simCode: createMinValueEquations"); end if; + ((uniqueEqIndex, maxValueEquations)) := BackendDAEUtil.foldEqSystem(inBackendDAE, SimCodeUtil.createMaxValueEquations, (uniqueEqIndex, {})); + if debug then ExecStat.execStat("simCode: createMaxValueEquations"); end if; + ((uniqueEqIndex, parameterEquations)) := BackendDAEUtil.foldEqSystem(inBackendDAE, SimCodeUtil.createVarNominalAssertFromVars, (uniqueEqIndex, {})); + if debug then ExecStat.execStat("simCode: createVarNominalAssertFromVars"); end if; + (uniqueEqIndex, parameterEquations, _) := SimCodeUtil.createParameterEquations(uniqueEqIndex, parameterEquations, inBackendDAE.shared.globalKnownVars); + parameterEquations := listReverse(parameterEquations); + if debug then ExecStat.execStat("simCode: createParameterEquations"); end if; + + discreteModelVars := BackendDAEUtil.foldEqSystem(inBackendDAE, SimCodeUtil.extractDiscreteModelVars, {}); + + //prepare DAEmode stuff + eqnsLst := BackendEquation.equationSystemsEqnsLst(inBackendDAE.eqs); + varsLst := BackendVariable.equationSystemsVarsLst(inBackendDAE.eqs); + daeVars := BackendVariable.listVar(varsLst); + daeEqns := BackendEquation.listEquation(eqnsLst); + // create SimCode residual equation + (daeEquations, uniqueEqIndex, tempVars) := SimCodeUtil.createEquationsfromList(listReverse(eqnsLst), varsLst, false, uniqueEqIndex, tempVars, inBackendDAE.shared.info); + + // state set stuff + (_, stateSets, uniqueEqIndex, tempVars, numStateSets) := SimCodeUtil.createStateSets(inBackendDAE, {}, uniqueEqIndex, tempVars); + if debug then ExecStat.execStat("simCode: createStateSets"); end if; + + // create model info + modelInfo := SimCodeUtil.createModelInfo(className, p, inBackendDAE, inInitDAE, functions, {}, numStateSets, fileDir, 0, tempVars); + + //create hash table + crefToSimVarHT := SimCodeUtil.createCrefToSimVarHT(modelInfo); + + // collect symbolic jacobians from state selection + (stateSets, modelInfo, SymbolicJacsStateSelect) := SimCodeUtil.addAlgebraicLoopsModelInfoStateSets(stateSets, modelInfo); + // collect symbolic jacobians in initialization loops of the overall jacobians + SymbolicJacsNLS := {}; + (initialEquations, modelInfo, SymbolicJacsTemp) := SimCodeUtil.addAlgebraicLoopsModelInfo(initialEquations, modelInfo); + SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS); + (parameterEquations, modelInfo, SymbolicJacsTemp) := SimCodeUtil.addAlgebraicLoopsModelInfo(parameterEquations, modelInfo); + SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS); + (symJacs, uniqueEqIndex) := SimCodeUtil.createSymbolicJacobianssSimCode({}, crefToSimVarHT, uniqueEqIndex, {"A", "B", "C", "D"}, {}); + (SymbolicJacs, modelInfo, SymbolicJacsTemp) := SimCodeUtil.addAlgebraicLoopsModelInfoSymJacs(symJacs, modelInfo); + SymbolicJacs := listAppend(SymbolicJacs, SymbolicJacsStateSelect); + // collect jacobian equation only for equantion info file + jacobianEquations := SimCodeUtil.collectAllJacobianEquations(SymbolicJacs); + if debug then ExecStat.execStat("simCode: create Jacobian linear code"); end if; + + SymbolicJacs := listAppend(listReverse(SymbolicJacsNLS), SymbolicJacs); + SymbolicJacs := listAppend(SymbolicJacs, SymbolicJacsTemp); + jacobianSimvars := SimCodeUtil.collectAllJacobianVars(SymbolicJacs); + modelInfo := SimCodeUtil.setJacobianVars(jacobianSimvars, modelInfo); + seedVars := SimCodeUtil.collectAllSeedVars(SymbolicJacs); + modelInfo := SimCodeUtil.setSeedVars(seedVars, modelInfo); + + + // create dae SimVars: residual and algebraic + // create residual variables, set index and push them SimCode Hash Table + ((_, resVars)) := BackendVariable.traverseBackendDAEVars(daeVars, BackendVariable.collectVarKindVarinVariables, (BackendVariable.isDAEmodeResVar, BackendVariable.emptyVars())); + ((residualVars, _)) := BackendVariable.traverseBackendDAEVars(resVars, SimCodeUtil.traversingdlowvarToSimvar, ({}, BackendVariable.emptyVars())); + residualVars := SimCodeUtil.rewriteIndex(residualVars, 0); + (residualVars, _) := SimCodeUtil.setVariableIndexHelper(residualVars, 0); + crefToSimVarHT:= List.fold(residualVars,SimCodeUtil.addSimVarToHashTable,crefToSimVarHT); + + // create auxiliary variables, set index and push them SimCode Hash Table + ((_, auxVars)) := BackendVariable.traverseBackendDAEVars(daeVars, BackendVariable.collectVarKindVarinVariables, (BackendVariable.isDAEmodeAuxVar, BackendVariable.emptyVars())); + ((auxiliaryVars, _)) := BackendVariable.traverseBackendDAEVars(auxVars, SimCodeUtil.traversingdlowvarToSimvar, ({}, BackendVariable.emptyVars())); + auxiliaryVars := SimCodeUtil.rewriteIndex(auxiliaryVars, 0); + (auxiliaryVars, _) := SimCodeUtil.setVariableIndexHelper(auxiliaryVars, 0); + crefToSimVarHT:= List.fold(auxiliaryVars,SimCodeUtil.addSimVarToHashTable,crefToSimVarHT); + + // filter states and der states from inBackendDAE.shared.localKnownVars + ((_, algVars)) := BackendVariable.traverseBackendDAEVars(inBackendDAE.shared.localKnownVars, BackendVariable.collectVarKindVarinVariables, (BackendVariable.isVarAlg, BackendVariable.emptyVars())); + ((algebraicVars, _)) := BackendVariable.traverseBackendDAEVars(algVars, SimCodeUtil.traversingdlowvarToSimvar, ({}, BackendVariable.emptyVars())); + //algebraicVars := SimCodeUtil.sortSimVarsAndWriteIndex(algebraicVars, crefToSimVarHT); + + // create DAE mode Sparse pattern and TODO: Jacobians + // sparsity pattern generation + daeModeJac := listGet(inBackendDAE.shared.symjacs, BackendDAE.SymbolicJacobianAIndex); + ({symDAESparsPattern}, uniqueEqIndex) := SimCodeUtil.createSymbolicJacobianssSimCode({daeModeJac}, crefToSimVarHT, uniqueEqIndex, {"daeMode"}, {}); + daeModeSP := SOME(symDAESparsPattern); + daeModeConf := SimCode.ALL_EQUATIONS(); + daeModeData := SOME(SimCode.DAEMODEDATA({daeEquations}, daeModeSP, residualVars, algebraicVars, auxiliaryVars, daeModeConf)); + + /* This is a *much* better estimate than the guessed number of equations */ + modelInfo := SimCodeUtil.addNumEqns(modelInfo, uniqueEqIndex); + + // update hash table + crefToSimVarHT := SimCodeUtil.createCrefToSimVarHT(modelInfo); + + simCode := SimCode.SIMCODE(modelInfo, + {}, // Set by the traversal below... + recordDecls, + includeDirs, + {}, + {}, + {}, + {}, + {}, + initialEquations, + {}, + removedInitialEquations, + startValueEquations, + nominalValueEquations, + minValueEquations, + maxValueEquations, + parameterEquations, + {}, + {}, + {}, + jacobianEquations, + stateSets, + {}, + {}, + zeroCrossings, + relations, + timeEvents, + discreteModelVars, + extObjInfo, + makefileParams, + SimCode.DELAYED_EXPRESSIONS(delayedExps, maxDelayedExpIndex), + SymbolicJacs, + simSettingsOpt, + filenamePrefix, + "", + "", + HpcOmSimCode.emptyHpcomData, + AvlTreeCRToInt.EMPTY(), + HashTableCrIListArray.emptyHashTable(), + HashTableCrILst.emptyHashTable(), + crefToSimVarHT, + HashTable.emptyHashTable(), + NONE(), + NONE(), + SimCode.emptyPartitionData, + daeModeData, + {} + ); + + (simCode, (_, _, lits)) := SimCodeUtil.traverseExpsSimCode(simCode, SimCodeFunctionUtil.findLiteralsHelper, literals); + simCode.literals := listReverse(lits); + + timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); + ExecStat.execStat("SimCode"); + + if Flags.isSet(Flags.SERIALIZED_SIZE) then + serializeNotify(simCode, filenamePrefix, "simCode"); + ExecStat.execStat("Serialize simCode"); + end if; + + if Flags.isSet(Flags.DUMP_SIMCODE) then + SimCodeUtil.dumpSimCodeDebug(simCode); + end if; + + System.realtimeTick(ClockIndexes.RT_CLOCK_TEMPLATES); + callTargetTemplates(simCode, Config.simCodeTarget()); + timeTemplates := System.realtimeTock(ClockIndexes.RT_CLOCK_TEMPLATES); + ExecStat.execStat("Templates"); + return; + else + setGlobalRoot(Global.stackoverFlowIndex, NONE()); + ErrorExt.rollbackNumCheckpoints(ErrorExt.getNumCheckpoints()-numCheckpoints); + Error.addInternalError("Stack overflow in "+getInstanceName()+"...\n"+stringDelimitList(StackOverflow.readableStacktraceMessages(), "\n"), sourceInfo()); + /* Do not fail or we can loop too much */ + StackOverflow.clearStacktraceMessages(); + end try annotation(__OpenModelica_stackOverflowCheckpoint=true); + fail(); +end generateModelCodeDAE; + protected function serializeNotify input T data; input String prefix; diff --git a/Compiler/SimCode/SimCodeUtil.mo b/Compiler/SimCode/SimCodeUtil.mo index 855888c2fed..a6d3004a6be 100644 --- a/Compiler/SimCode/SimCodeUtil.mo +++ b/Compiler/SimCode/SimCodeUtil.mo @@ -129,8 +129,7 @@ algorithm end sortEqSystems; protected function simulationFindLiterals - "Finds all literal expressions in the DAE" - input BackendDAE.BackendDAE dae; + "Finds all literal expressions in functionsa" input list fns; output list ofns; output tuple> literals; @@ -519,7 +518,7 @@ algorithm crefToSimVarHT:= List.fold(residualVars,addSimVarToHashTable,crefToSimVarHT); algebraicVars := sortSimVarsAndWriteIndex(algebraicVars, crefToSimVarHT); daeModeConf := match Flags.getConfigEnum(Flags.DAE_MODE) case 2 then SimCode.ALL_EQUATIONS(); case 3 then SimCode.DYNAMIC_EQUATIONS(); end match; - daeModeData := SOME(SimCode.DAEMODEDATA(daeEquations, daeModeSP, residualVars, algebraicVars, daeModeConf)); + daeModeData := SOME(SimCode.DAEMODEDATA(daeEquations, daeModeSP, residualVars, algebraicVars, {}, daeModeConf)); else daeModeData := NONE(); end if; @@ -630,7 +629,7 @@ end createSimCode; public function createFunctions input Absyn.Program inProgram; - input BackendDAE.BackendDAE inBackendDAE; + input DAE.FunctionTree functionTree; output list outLibs; output list outLibPaths; output list outIncludes; @@ -640,15 +639,13 @@ public function createFunctions output tuple> outLiterals; protected list funcelems; - DAE.FunctionTree functionTree; list lits; algorithm try - BackendDAE.DAE(shared=BackendDAE.SHARED(functionTree=functionTree)) := inBackendDAE; // get all the used functions from the function tree funcelems := DAEUtil.getFunctionList(functionTree); funcelems := Inline.inlineCallsInFunctions(funcelems, (NONE(), {DAE.NORM_INLINE(), DAE.AFTER_INDEX_RED_INLINE()}), {}); - (funcelems, outLiterals as (_, _, lits)) := simulationFindLiterals(inBackendDAE, funcelems); + (funcelems, outLiterals as (_, _, lits)) := simulationFindLiterals(funcelems); (outFunctions, outRecordDecls, outIncludes, outIncludeDirs, outLibs, outLibPaths) := SimCodeFunctionUtil.elaborateFunctions(inProgram, funcelems, {}, lits, {}); // Do we need metarecords here as well? else Error.addInternalError("Creation of Modelica functions failed.", sourceInfo()); @@ -916,7 +913,7 @@ algorithm end for; end addTempVars; -protected function setJacobianVars "author: unknown +public function setJacobianVars "author: unknown Set the given jacobian vars in the given model info. The old jacobian variables will be replaced." input list iJacobianVars; input SimCode.ModelInfo iModelInfo; @@ -931,7 +928,7 @@ algorithm end if; end setJacobianVars; -protected function setSeedVars +public function setSeedVars "Set the given seed vars in the given model info, replacing old seed vars. author: rfranke" input list seedVars; @@ -944,7 +941,7 @@ algorithm modelInfo.vars := vars; end setSeedVars; -protected function addNumEqns +public function addNumEqns input SimCode.ModelInfo modelInfo; input Integer numEqns; output SimCode.ModelInfo omodelInfo = modelInfo; @@ -1056,7 +1053,7 @@ algorithm end match; end setSystemIndexMap; -protected function addAlgebraicLoopsModelInfo " +public function addAlgebraicLoopsModelInfo " Adds algebraic loops from list of SimEqSystem into ModelInfo and SimEqSystem equation algebraic system index." input output list eqns; @@ -1199,7 +1196,7 @@ algorithm end if; end updateLinearSyst; -protected function addAlgebraicLoopsModelInfoSymJacs " +public function addAlgebraicLoopsModelInfoSymJacs " Adds algebraic loops from list of SimEqSystem into ModelInfo and SimEqSystem equation algebraic system index." input output list symjacs; @@ -1236,7 +1233,7 @@ algorithm outSymJacsInSymJacs := listReverse(outSymJacsInSymJacs); end addAlgebraicLoopsModelInfoSymJacs; -protected function addAlgebraicLoopsModelInfoStateSets +public function addAlgebraicLoopsModelInfoStateSets " function to collect jacobians for statesets" input list inSets; input SimCode.ModelInfo inModelInfo; @@ -1890,7 +1887,7 @@ tuple> /* daeEquations */, BackendDAE.EquationArray /* daeMode equations */ >; -protected function createDAEEquations +public function createDAEEquations "Creates DAE equations of the form: residualVar = eqRHS - eqLHS " input BackendDAE.EqSystems inSysts; @@ -2126,7 +2123,7 @@ algorithm end try; end createDAEEquationForComp; -protected function createDaeModeSparsePattern +public function createDaeModeSparsePattern "create sparse pattern for daeMode equations and variables. the sparsity pattern is determined just using adjacency matrix, since no other dependencies are necessary " @@ -2202,7 +2199,7 @@ algorithm sparsetupleT := list((cr,t) threaded for cr in varCrefs, t in translated); // build sparse pattern - bdaeSP :=(sparsetuple, sparsetupleT, (varCrefsList, varCrefsList), nonZeroElements); + bdaeSP :=(sparsetupleT, sparsetuple, (varCrefsList, varCrefsList), nonZeroElements); if debug then BackendDump.dumpSparsityPattern(bdaeSP, "DAE mode sparsity pattern"); @@ -2214,11 +2211,13 @@ algorithm // or without coloring //coloring := List.transposeList({varCrefsList}); + // translate to SimCode sparsity (simCodeJac, _) := createSimCodeSparsePattenDAEmode({(NONE(), bdaeSP, coloring)}, crefToSimVarHT, 0, "daeMode"); outSimCodeJac := SOME(simCodeJac); else + outSimCodeJac := NONE(); Error.addInternalError("function createDaeModeSparsePattern failed", sourceInfo()); end try; end createDaeModeSparsePattern; @@ -2237,7 +2236,7 @@ algorithm end if; end getSimCodeDAEModeDataEqns; -protected function sortSimVarsAndWriteIndex +public function sortSimVarsAndWriteIndex input list inSimVar; input SimCode.HashTableCrefToSimVar crefToSimVarHT; output list outSimVar; @@ -3260,7 +3259,7 @@ algorithm end match; end createTempVars; -protected function createNonlinearResidualEquations +public function createNonlinearResidualEquations input list eqs; input Integer iuniqueEqIndex; input list itempvars; @@ -4147,7 +4146,7 @@ end createTornSystemInnerEqns1; // // ============================================================================= -protected function createStateSets "author: Frenkel TUD 2012 +public function createStateSets "author: Frenkel TUD 2012 This function handle states sets for code generation." input BackendDAE.BackendDAE inDAE; input list iEquations; @@ -4464,7 +4463,7 @@ algorithm end if; end getFurtherVars; -protected function createJacobianLinearCode +public function createJacobianLinearCode input BackendDAE.SymbolicJacobians inSymjacs; input SimCode.ModelInfo inModelInfo; input Integer iuniqueEqIndex; @@ -4502,7 +4501,7 @@ algorithm end match; end checkForEmptyBDAE; -protected function createSymbolicJacobianssSimCode +public function createSymbolicJacobianssSimCode "function creates the linear model matrices column-wise author: wbraun" input BackendDAE.SymbolicJacobians inSymJacobians; @@ -4840,7 +4839,7 @@ algorithm end match; end createAllDiffedSimVars; -protected function collectAllJacobianEquations +public function collectAllJacobianEquations input list inJacobianMatrix; output list outEqn = {}; protected @@ -4856,7 +4855,7 @@ algorithm end for; end collectAllJacobianEquations; -protected function collectAllJacobianVars +public function collectAllJacobianVars input list inJacobianMatrix; output list outVars = {}; protected @@ -4872,7 +4871,7 @@ algorithm end for; end collectAllJacobianVars; -protected function collectAllSeedVars +public function collectAllSeedVars "Collect seed vars of Jacobian matrices. author: rfranke" input list inJacobianMatrices; output list outVars = {}; @@ -5106,7 +5105,7 @@ algorithm end for; end dumpSparsePattern; -protected function createSimCodeSparsePattenDAEmode +public function createSimCodeSparsePattenDAEmode "function translates the sparse pattern of the daeMode author: wbraun" input BackendDAE.SymbolicJacobians inSymJacobian; @@ -5162,10 +5161,6 @@ algorithm print("diffedCrefs: " + ComponentReference.printComponentRefListStr(diffedCompRefs) + "\n"); print("\n---+++ indexVars +++---\n"); print(Tpl.tplString(SimCodeDump.dumpVarsShort, indexVars)); - print("\n---+++ sparse pattern vars +++---\n"); - dumpSparsePattern(sparsepattern); - print("\n---+++ sparse pattern transpose +++---\n"); - dumpSparsePattern(sparsepatternT); end if; seedVars = rewriteIndex(seedVars, 0); indexVars = rewriteIndex(indexVars, 0); @@ -5239,7 +5234,7 @@ algorithm end match; end collectDelayExpressions; -protected function extractDelayedExpressions +public function extractDelayedExpressions input BackendDAE.BackendDAE dlow; output list>> delayedExps; output Integer maxDelayedExpIndex; @@ -5276,7 +5271,7 @@ algorithm end match; end extractIdAndExpFromDelayExp; -protected function createExtObjInfo +public function createExtObjInfo input BackendDAE.Shared shared; output SimCode.ExtObjInfo extObjInfo; protected @@ -5394,7 +5389,7 @@ algorithm end matchcontinue; end traversedlowEqToSimEqSystem; -protected function extractDiscreteModelVars +public function extractDiscreteModelVars input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; input list acc; @@ -5660,7 +5655,7 @@ algorithm end matchcontinue; end createEquationsIfBranch; -protected function createEquationsfromList +public function createEquationsfromList input list inEquations; input list inVars; input Boolean genDiscrete; @@ -6244,7 +6239,7 @@ algorithm end matchcontinue; end createSingleAlgorithmCode; -protected function createInitialEquations "author: lochel" +public function createInitialEquations "author: lochel" input BackendDAE.BackendDAE inInitDAE; input Integer iuniqueEqIndex; input list itempvars; @@ -6283,7 +6278,7 @@ algorithm otempvars := tempvars; end createInitialEquations; -protected function createInitialEquations_lambda0 "author: lochel" +public function createInitialEquations_lambda0 "author: lochel" input BackendDAE.BackendDAE inInitDAE; input Integer iuniqueEqIndex; input list itempvars; @@ -6430,7 +6425,7 @@ algorithm ouniqueEqIndex := iuniqueEqIndex+1; end dlowAlgToSimEqSystem; -protected function createVarNominalAssertFromVars +public function createVarNominalAssertFromVars input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; input tuple> acc; @@ -6451,7 +6446,7 @@ algorithm end match; end createVarNominalAssertFromVars; -protected function createStartValueEquations +public function createStartValueEquations input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; input tuple, BackendDAE.Variables > acc; @@ -6483,7 +6478,7 @@ algorithm end matchcontinue; end createStartValueEquations; -protected function createNominalValueEquations +public function createNominalValueEquations input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; input tuple> acc; @@ -6512,7 +6507,7 @@ algorithm end matchcontinue; end createNominalValueEquations; -protected function createMinValueEquations +public function createMinValueEquations input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; input tuple> acc; @@ -6541,7 +6536,7 @@ algorithm end matchcontinue; end createMinValueEquations; -protected function createMaxValueEquations +public function createMaxValueEquations input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; input tuple> acc; @@ -6587,7 +6582,7 @@ algorithm outUniqueEqIndex := inUniqueEqIndex+1; end makeSolved_SES_SIMPLE_ASSIGN_fromStartValue; -protected function createParameterEquations +public function createParameterEquations "Traverses the globalKnownVars and creates simEqns for the variable if necessary." input Integer inUniqueEqIndex; input list acc; @@ -7652,6 +7647,8 @@ algorithm addSimVar(simVar, SimVarsIndex.realOptimizeFinalConstraints, simVars); elseif BackendVariable.isOptInputVar(dlowVar) then addSimVar(simVar, SimVarsIndex.alg, simVars); + elseif BackendVariable.isDAEmodeVar(dlowVar) then + // skip, they are only used localy in daeMode else Error.addInternalError("Failed to find the correct SimVar list for Var: " + BackendDump.varString(dlowVar), sourceInfo()); end if; @@ -8276,6 +8273,33 @@ algorithm str := str + "Hold Events: "+boolString(subPart.holdEvents); end subPartitionString; +public function dumpSimCodeDAEmodeDataString + input Option inDaeModedata; + output String str; +algorithm + _ := match(inDaeModedata) + local + SimCode.DaeModeData dmd; + SimCode.SparsityPattern sparsityT; + case(SOME(dmd)) algorithm + print("\ndaeMode: \n" + UNDERLINE + "\n"); + str := "residual Equations:\n"+UNDERLINE+"\n"; + print(str); + dumpSimEqSystemLst(List.flatten(dmd.daeEquations),"\n"); + dumpVarLst(dmd.residualVars,"residualVars("+intString(listLength(dmd.residualVars))+")"); + dumpVarLst(dmd.algebraicVars,"algebraicDAEVars("+intString(listLength(dmd.algebraicVars))+")"); + dumpVarLst(dmd.auxiliaryVars,"auxVars("+intString(listLength(dmd.auxiliaryVars))+")"); + if isSome(dmd.sparsityPattern) then + str := "Sparsity Pattern:\n"+UNDERLINE+"\n"; + print(str); + SimCode.JAC_MATRIX(sparsityT=sparsityT) := Util.getOption(dmd.sparsityPattern); + dumpSparsePatternInt(sparsityT); + end if; + then (); + case(NONE()) then (); + end match; +end dumpSimCodeDAEmodeDataString; + public function dumpSimCodeDebug"prints the simcode debug output to std out." input SimCode.SimCode simCode; protected @@ -8329,6 +8353,7 @@ algorithm List.map_0(jacObs,dumpJacobianMatrix); print("\nmodelInfo: \n" + UNDERLINE + "\n"); dumpModelInfo(simCode.modelInfo); + dumpSimCodeDAEmodeDataString(simCode.daeModeData); end dumpSimCodeDebug; protected function isAliasVar @@ -8482,7 +8507,7 @@ algorithm end for; end fixIndex; -protected function rewriteIndex +public function rewriteIndex input list inVars; output list outVars = {}; input output Integer index; @@ -8508,7 +8533,7 @@ algorithm end for; end setVariableIndex; -protected function setVariableIndexHelper +public function setVariableIndexHelper input list inVars; input Integer inIndex; output list outVars; @@ -9012,7 +9037,7 @@ algorithm (_, outTpl) := traversingdlowvarToSimvar(v, inTpl); end traversingdlowvarToSimvarFold; -protected function traversingdlowvarToSimvar +public function traversingdlowvarToSimvar input output BackendDAE.Var var; input tuple, BackendDAE.Variables> inTpl; output tuple, BackendDAE.Variables> outTpl; @@ -10696,7 +10721,7 @@ algorithm end traveseSimVars; -protected function traverseExpsSimCode +public function traverseExpsSimCode input SimCode.SimCode simCode; input Func func; input A ia; diff --git a/Compiler/Template/CodegenC.tpl b/Compiler/Template/CodegenC.tpl index edec20a49a9..b08e93ab15b 100644 --- a/Compiler/Template/CodegenC.tpl +++ b/Compiler/Template/CodegenC.tpl @@ -856,12 +856,16 @@ template simulationFile_dae_header(SimCode simCode) "DAEmode header generation" ::= match simCode - case simCode as SIMCODE(daeModeData=SOME(DAEMODEDATA(residualVars=residualVars))) then + case simCode as SIMCODE(daeModeData=SOME(DAEMODEDATA(residualVars=residualVars,auxiliaryVars=auxiliaryVars))) then << /* residual variable define for daeMode */ <%residualVars |> var => defineSimVarArray(var, "residualVars") ;separator="\n"%> + /* auxiliary variable define for daeMode */ + <%auxiliaryVars |> var => + defineSimVarArray(var, "auxiliaryVars") + ;separator="\n"%> >> /* adrpo: leave a newline at the end of file to get rid of the warning */ case simCode as SIMCODE(__) then @@ -880,12 +884,13 @@ template simulationFile_dae(SimCode simCode) match simCode case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(__)), daeModeData=SOME(DAEMODEDATA(daeEquations=daeEquations, sparsityPattern=sparsityPattern, - algebraicDAEVars=algebraicDAEVars, residualVars=residualVars))) then + algebraicVars=algebraicVars, residualVars=residualVars, + auxiliaryVars=auxiliaryVars))) then let modelNamePrefixStr = modelNamePrefix(simCode) let initDAEmode = match sparsityPattern - case SOME(JAC_MATRIX(sparsityT=sparse, coloredCols=colorList, maxColorCols=maxColor)) then - '<%initializeDAEmodeData(listLength(residualVars), listLength(algebraicDAEVars), sparse, colorList, maxColor, modelNamePrefixStr)%>' + case SOME(JAC_MATRIX(sparsity=sparse, coloredCols=colorList, maxColorCols=maxColor)) then + '<%initializeDAEmodeData(listLength(residualVars), listLength(algebraicVars), listLength(auxiliaryVars), sparse, colorList, maxColor, modelNamePrefixStr)%>' case NONE() then 'int <%symbolName(modelNamePrefixStr,"initializeDAEmodeData")%>(DATA *inData, DAEMODE_DATA* daeModeData){ return -1; }' end match @@ -900,7 +905,7 @@ template simulationFile_dae(SimCode simCode) <%evaluateDAEResiduals(daeEquations, modelNamePrefixStr)%> - <%algebraicDAEVar(algebraicDAEVars, modelNamePrefixStr)%> + <%algebraicDAEVar(algebraicVars, modelNamePrefixStr)%> <%initDAEmode%> @@ -4092,7 +4097,7 @@ template algebraicDAEVar(list algVars, String modelNamePrefix) >> end algebraicDAEVar; -template initializeDAEmodeData(Integer nResVars, Integer nAlgVars, list>> sparsepattern, list> colorList, Integer maxColor, String modelNamePrefix) +template initializeDAEmodeData(Integer nResVars, Integer nAlgVars, Integer nAuxVars, list>> sparsepattern, list> colorList, Integer maxColor, String modelNamePrefix) "Generates initialization function for daeMode." ::= let sizeCols = listLength(sparsepattern) @@ -4114,8 +4119,10 @@ template initializeDAEmodeData(Integer nResVars, Integer nAlgVars, listnResidualVars = <%nResVars%>; daeModeData->nAlgebraicDAEVars = <%nAlgVars%>; + daeModeData->nAuxiliaryVars = <%nAuxVars%>; daeModeData->residualVars = (double*) malloc(sizeof(double)*<%nResVars%>); + daeModeData->auxiliaryVars = (double*) malloc(sizeof(double)*<%nAuxVars%>); /* set the function pointer */ daeModeData->evaluateDAEResiduals = <%symbolName(modelNamePrefix,"evaluateDAEResiduals")%>; diff --git a/Compiler/Template/CodegenCFunctions.tpl b/Compiler/Template/CodegenCFunctions.tpl index 096f902242b..d99e8d64b8b 100644 --- a/Compiler/Template/CodegenCFunctions.tpl +++ b/Compiler/Template/CodegenCFunctions.tpl @@ -4104,6 +4104,7 @@ template crefToCStr(ComponentRef cr, Integer ix, Boolean isPre, Boolean isStart) case SIMVAR(varKind=JAC_DIFF_VAR()) case SIMVAR(varKind=SEED_VAR()) case SIMVAR(varKind=DAE_RESIDUAL_VAR()) + case SIMVAR(varKind=DAE_AUX_VAR()) case SIMVAR(index=-2) then if intEq(ix,0) then (if isPre then "$P$PRE")+crefDefine(cr) diff --git a/Compiler/Template/CodegenCpp.tpl b/Compiler/Template/CodegenCpp.tpl index d2d092c3546..d454c4d98fd 100644 --- a/Compiler/Template/CodegenCpp.tpl +++ b/Compiler/Template/CodegenCpp.tpl @@ -9542,7 +9542,7 @@ end clockIntervalsInit; template dimension1(SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace) ::= match simCode - case SIMCODE(modelInfo = MODELINFO(varInfo = vi as VARINFO(__)),daeModeData=SOME(DAEMODEDATA(algebraicDAEVars=algebraicDAEVars, residualVars=residualVars)), partitionData = PARTITIONDATA(__)) + case SIMCODE(modelInfo = MODELINFO(varInfo = vi as VARINFO(__)),daeModeData=SOME(DAEMODEDATA(algebraicVars=algebraicVars, residualVars=residualVars)), partitionData = PARTITIONDATA(__)) then let numRealVars = numRealvars(modelInfo) let numIntVars = numIntvars(modelInfo) @@ -9550,8 +9550,8 @@ template dimension1(SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text let numStringVars = numStringvars(modelInfo) << _dimContinuousStates = <%vi.numStateVars%>; - _dimAE = <%listLength(algebraicDAEVars)%>; - _dimRHS = <%intAdd(vi.numStateVars,listLength(algebraicDAEVars))%>; + _dimAE = <%listLength(algebraicVars)%>; + _dimRHS = <%intAdd(vi.numStateVars,listLength(algebraicVars))%>; _dimBoolean = <%numBoolVars%>; _dimInteger = <%numIntVars%>; _dimString = <%numStringVars%>; @@ -13912,7 +13912,7 @@ template simulationDAEMethodsDeclaration(SimCode simCode) match simCode case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(__)), daeModeData=SOME(DAEMODEDATA(daeEquations=daeEquations, sparsityPattern=sparsityPattern, - algebraicDAEVars=algebraicDAEVars, residualVars=residualVars))) then + algebraicVars=algebraicDAEVars, residualVars=residualVars))) then << <%generateDAEEquationMemberFuncDecls(daeEquations,"evaluateDAE")%> @@ -13952,7 +13952,7 @@ template simulationDAEMethods(SimCode simCode,Text& extraFuncs,Text& extraFuncsD match simCode case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(__)), daeModeData=SOME(DAEMODEDATA(daeEquations=daeEquations, sparsityPattern=sparsityPattern, - algebraicDAEVars=algebraicDAEVars, residualVars=residualVars))) then + algebraicVars=algebraicDAEVars, residualVars=residualVars))) then let modelNamePrefixStr = lastIdentOfPath(modelInfo.name) << diff --git a/Compiler/Template/CodegenUtil.tpl b/Compiler/Template/CodegenUtil.tpl index 35d7a03a96a..b1882a11119 100644 --- a/Compiler/Template/CodegenUtil.tpl +++ b/Compiler/Template/CodegenUtil.tpl @@ -217,6 +217,7 @@ template variabilityString(VarKind varKind) case OPT_LOOP_INPUT() then "OPT_LOOP_INPUT" case ALG_STATE() then "ALG_STATE" case DAE_RESIDUAL_VAR() then "DAE_RESIDUAL_VAR" + case DAE_AUX_VAR() then "DAE_AUX_VAR" else "#UNKNOWN_VARKIND" end match end variabilityString; diff --git a/Compiler/Template/SimCodeTV.mo b/Compiler/Template/SimCodeTV.mo index 80e39e6b997..073f85f8dab 100644 --- a/Compiler/Template/SimCodeTV.mo +++ b/Compiler/Template/SimCodeTV.mo @@ -608,7 +608,8 @@ package SimCode list> daeEquations "daeModel residuals equations"; Option sparsityPattern "contains the sparsity pattern for the daeMode"; list residualVars; // variable used to calculate residuals of a DAE form, they are real - list algebraicDAEVars; // variable used to calculate residuals of a DAE form, they are real + list algebraicVars; // algebraic variable used to calculate residuals of a DAE form, they are real + list auxiliaryVars; // auxiliary variable used to calculate residuals of a DAE form, they are real end DAEMODEDATA; end DaeModeData; @@ -1222,6 +1223,7 @@ package BackendDAE record ALG_STATE end ALG_STATE; // algebraic state used by inline solver record ALG_STATE_OLD end ALG_STATE_OLD; // algebraic state old value used by inline solver record DAE_RESIDUAL_VAR end DAE_RESIDUAL_VAR; // variable kind used for DAEmode + record DAE_AUX_VAR end DAE_AUX_VAR; // auxiliary variable used for DAEmode end VarKind; uniontype SubClock diff --git a/Compiler/Util/Config.mo b/Compiler/Util/Config.mo index 431ba72a3eb..4b7a4901cc3 100644 --- a/Compiler/Util/Config.mo +++ b/Compiler/Util/Config.mo @@ -327,6 +327,12 @@ algorithm outStringLst := Flags.getConfigStringList(Flags.POST_OPT_MODULES); end getPostOptModules; +public function getPostOptModulesDAE + output list outStringLst; +algorithm + outStringLst := Flags.getConfigStringList(Flags.POST_OPT_MODULES_DAE); +end getPostOptModulesDAE; + public function getInitOptModules output list outStringLst; algorithm diff --git a/Compiler/Util/Flags.mo b/Compiler/Util/Flags.mo index f864f7d11e1..120d8c12669 100644 --- a/Compiler/Util/Flags.mo +++ b/Compiler/Util/Flags.mo @@ -1314,11 +1314,12 @@ constant ConfigFlag CT_STATE_MACHINES = CONFIG_FLAG(94, "ctStateMachines", Util.gettext("Experimental: Enable continuous-time state machine prototype")); constant ConfigFlag DAE_MODE = CONFIG_FLAG(95, "daeMode", - NONE(), EXTERNAL(), ENUM_FLAG(1, {("none", 1), ("all",2), ("dynamic",3)}), + NONE(), EXTERNAL(), ENUM_FLAG(1, {("none", 1), ("all",2), ("dynamic",3), ("new",4)}), SOME(STRING_OPTION({"none", "all", "dynamic"})), Util.gettext("Generates additional code for DAE mode, where the equations are not causelized, when one of the following option is selected:\n"+ - "all : In this mode all equations are passed to the integrator.\n"+ - "dynamic : In this mode only the equation for the dynamic part of the system are passed to the integrator.") + "all : In this mode all equations are passed to the integrator.\n"+ + "dynamic : In this mode only the equation for the dynamic part of the system are passed to the integrator."+ + "new : This option enables the new daeMode. Currently alpha development status.\n") ); constant ConfigFlag INLINE_METHOD = CONFIG_FLAG(96, "inlineMethod", @@ -1432,6 +1433,23 @@ constant ConfigFlag IGNORE_REPLACEABLE = CONFIG_FLAG(117, "ignoreReplaceable", "", NONE(), INTERNAL(), BOOL_FLAG(false), NONE(), Util.gettext("Is true when building a model (as opposed to running a Modelica script).")); + constant ConfigFlag POST_OPT_MODULES_DAE = CONFIG_FLAG(124, "postOptModulesDAE", + NONE(), EXTERNAL(), STRING_LIST_FLAG({ + "lateInlineFunction", + "wrapFunctionCalls", + //"replaceDerCalls", + "simplifysemiLinear", + "simplifyComplexFunction", + "calculateStateSetsJacobians", + "removeConstants", + "simplifyTimeIndepFuncCalls", + "simplifyAllExpressions", + "findZeroCrossings", + "createDAEmodeBDAE", + "detectDAEmodeSparsePattern" + }),NONE(), + Util.gettext("Sets the optimization modules for the DAEmode in the back end. See --help=optmodules for more info.")); + protected // This is a list of all configuration flags. A flag can not be used unless it's // in this list, and the list is checked at initialization so that all flags are @@ -1559,7 +1577,8 @@ constant list allConfigFlags = { LOAD_MSL_MODEL, Load_PACKAGE_FILE, BUILDING_FMU, - BUILDING_MODEL + BUILDING_MODEL, + POST_OPT_MODULES_DAE }; public function new diff --git a/Compiler/boot/LoadCompilerSources.mos b/Compiler/boot/LoadCompilerSources.mos index 76fe6360573..ff7f63b5af8 100644 --- a/Compiler/boot/LoadCompilerSources.mos +++ b/Compiler/boot/LoadCompilerSources.mos @@ -279,6 +279,7 @@ if true then /* Suppress output */ "../BackEnd/Causalize.mo", "../BackEnd/CommonSubExpression.mo", "../BackEnd/DAEQuery.mo", + "../BackEnd/DAEMode.mo", "../BackEnd/Differentiate.mo", "../BackEnd/DumpGraphML.mo", "../BackEnd/DumpHTML.mo", diff --git a/SimulationRuntime/c/simulation/solver/ida_solver.c b/SimulationRuntime/c/simulation/solver/ida_solver.c index a80b1e00866..6543afffa45 100644 --- a/SimulationRuntime/c/simulation/solver/ida_solver.c +++ b/SimulationRuntime/c/simulation/solver/ida_solver.c @@ -91,6 +91,10 @@ static int idaReScaleData(IDA_SOLVER *idaData); static int idaScaleVector(N_Vector vec, double* factors, unsigned int size); static int idaReScaleVector(N_Vector vec, double* factors, unsigned int size); +static IDA_SOLVER *idaDataGlobal; +static int initializedSolver = 0; +int ida_calcReinitAfterEvent(DATA* data, threadData_t *threadData); + int checkIDAflag(int flag) { @@ -643,6 +647,12 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo N_VSetArrayPointer_Serial((data->simulationInfo->sensitivityMatrix + i*idaData->N), idaData->ySResult[i]); } } + /* for the event handling in the dae mode */ + if (compiledInDAEMode == 4){ + idaDataGlobal = idaData; + initializedSolver = 1; + data->callback->functionDAE = ida_calcReinitAfterEvent; + } free(tmp); TRACE_POP @@ -685,6 +695,43 @@ ida_solver_deinitial(IDA_SOLVER *idaData){ return 0; } +int +ida_calcReinitAfterEvent(DATA* data, threadData_t *threadData) +{ + IDA_SOLVER *idaData = idaDataGlobal; + int flag; + if (compiledInDAEMode == 4){ + if (initializedSolver){ + data->simulationInfo->discreteCall = 1; + + memcpy(idaData->states, data->localData[0]->realVars, sizeof(double)*data->modelData->nStates); + + data->simulationInfo->daeModeData->getAlgebraicDAEVars(data, threadData, idaData->states + data->modelData->nStates); + memcpy(idaData->statesDer, data->localData[1]->realVars + data->modelData->nStates, sizeof(double)*data->modelData->nStates); + + flag = IDAReInit(idaData->ida_mem, + data->localData[0]->timeValue, + idaData->y, + idaData->yp); + + //flag = IDASetStepToleranceIC(idaData->ida_mem, 1e-12); + IDASetMaxNumStepsIC(idaData->ida_mem, 2*data->modelData->nStates*10); + IDASetMaxNumJacsIC(idaData->ida_mem, 2*data->modelData->nStates*10); + IDASetMaxNumItersIC(idaData->ida_mem, 2*data->modelData->nStates*10); + flag = IDACalcIC(idaData->ida_mem, IDA_YA_YDP_INIT, data->localData[0]->timeValue+1); + if (checkIDAflag(flag)){ + throwStreamPrint(threadData, "##IDA## discrete update failed flag %d!", flag); + } + + data->simulationInfo->discreteCall = 0; + } + } + else{ + data->callback->functionDAE(data, threadData); + } + +} + /* main ida function to make a step */ int ida_solver_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo) @@ -774,7 +821,6 @@ ida_solver_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo) throwStreamPrint(threadData, "##IDA## set IDASensInit failed!"); } } - idaData->setInitialSolution = 1; } diff --git a/SimulationRuntime/c/simulation_data.h b/SimulationRuntime/c/simulation_data.h index 61725f9aa8f..fa5cd017400 100644 --- a/SimulationRuntime/c/simulation_data.h +++ b/SimulationRuntime/c/simulation_data.h @@ -421,9 +421,15 @@ typedef struct DAEMODE_DATA /* number of algebraic variables */ long nAlgebraicDAEVars; + /* number of algebraic variables */ + long nAuxiliaryVars; + /* workspace for the residual variables */ modelica_real* residualVars; + /* workspace for the auxiliary variables */ + modelica_real* auxiliaryVars; + /* daeMode sparse pattern */ SPARSE_PATTERN* sparsePattern;