From bc38d8eeadb293c5e2d7c9f73c349a72538c3623 Mon Sep 17 00:00:00 2001 From: rfranke Date: Thu, 8 Jul 2021 23:00:08 +0200 Subject: [PATCH] Improve treatment of unknown dimensions in Cpp runtime (#7677) See ModelicaTest.Math.TestMatrices3 (MSL 4.0.0) ERROR : init : SimManager: Could not initialize system ERROR : init : SimManager: std::bad_alloc --- OMCompiler/Compiler/Template/CodegenCpp.tpl | 47 ++++++++----------- .../Compiler/Template/CodegenCppOld.tpl | 47 ++++++++----------- .../cpp/Core/Math/ArrayOperations.cpp | 10 ++-- 3 files changed, 44 insertions(+), 60 deletions(-) diff --git a/OMCompiler/Compiler/Template/CodegenCpp.tpl b/OMCompiler/Compiler/Template/CodegenCpp.tpl index 0f8098464ca..dd6b87c7767 100644 --- a/OMCompiler/Compiler/Template/CodegenCpp.tpl +++ b/OMCompiler/Compiler/Template/CodegenCpp.tpl @@ -5088,14 +5088,16 @@ match var */ case var as VARIABLE(__) then let marker = '<%contextCref(var.name,contextFunction,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)%>' - let &varInits += '/* varOutputTuple varInits(<%marker%>) */ <%\n%>' - let &varAssign += '// varOutput varAssign(<%marker%>) <%\n%>' + let &varInits += '// varOutputTuple varInits(<%marker%>)<%\n%>' + let &varAssign += '// varOutput varAssign(<%marker%>)<%\n%>' + let testinstDimsInit = (instDims |> dim => testDaeDimension(dim);separator="") let instDimsInit = (instDims |> dim => daeDimension(dim, contextFunction, &varInits, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation) ;separator=",") let assginBegin = 'get<<%ix%>>' if instDims then - let &varInits += '<%assginBegin%>(/*_<%fname%>*/output.data).setDims(<%instDimsInit%>);//todo setDims not for stat arrays - <%\n%>' + // don't setDims for static or unknown dimensions, treated as "" and "---", respectively + let &varInits += if boolAnd(intGt(stringLength(testinstDimsInit), 0), intEq(-1, stringFind(testinstDimsInit, "---"))) then + '<%assginBegin%>(/*_<%fname%>*/output.data).setDims(<%instDimsInit%>);<%\n%>' let &varAssign += '<%assginBegin%>(/*_<%fname%>*/output.data)=<%contextCref(var.name,contextFunction,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace,stateDerVectorName,useFlatArrayNotation)%>;<%\n%>' "" else @@ -5225,13 +5227,16 @@ template recordMemberInit(Var v, Text varName, Text &preExp /*BUFP*/, Text &varD end recordMemberInit; template setDims(Text testinstDimsInit, String varName , Text &varInits, String instDimsInit) + "call varName.setDims for dynamic and known dimensions" ::= match testinstDimsInit - case "" then let &varInits += '' + case "" then "" - else let &varInits += '<%varName%>.setDims(<%instDimsInit%>);<%\n%>' + else + let &varInits += if intEq(-1, stringFind(testinstDimsInit, "---")) then + '<%varName%>.setDims(<%instDimsInit%>);<%\n%>' "" - end match + end match end setDims; @@ -5397,8 +5402,8 @@ case var as VARIABLE(__) then let &varInits = buffer "" let testinstDimsInit = (instDims |> dim => testDaeDimension(dim);separator="") let instDimsInit = (instDims |> dim => daeDimension(dim, contextFunction, &varInits, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation);separator=",") - // check for unknown dimension that is treated as -1 - if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(instDimsInit, "-"))) then + // check for static and known dimension + if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(testinstDimsInit, "---"))) then if instDims then 'StatArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>, <%instDimsInit%>>& ' else expTypeFlag(var.ty, 5) else if instDims then 'DynArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>>/*<%instDimsInit%>*/&' else expTypeFlag(var.ty, 5) @@ -5412,8 +5417,8 @@ case var as VARIABLE(__) then let &varInits = buffer "" // should be empty let testinstDimsInit = (instDims |> dim => testDaeDimension(dim);separator="") let instDimsInit = (instDims |> dim => daeDimension(dim, contextFunction, &varInits, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, "stateDerVectorName_not_given", false /*is false the default?*/);separator=",") - // check for unknown dimension that is treated as -1 - if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(instDimsInit, "-"))) then + // check for static and known dimension + if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(testinstDimsInit, "---"))) then if instDims then 'StatArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>, <%instDimsInit%>> ' else expTypeArrayIf(var.ty) else if instDims then 'DynArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>>/*<%instDimsInit%>*/ ' else expTypeArrayIf(var.ty) @@ -9340,21 +9345,6 @@ bool <%lastIdentOfPath(modelInfo.name)%>::isODE() >> end isODE; -template testdimension(Dimension d) -::= - match d - case DAE.DIM_BOOLEAN(__) then '' - case DAE.DIM_INTEGER(__) then '' - case DAE.DIM_ENUM(__) then '' - case DAE.DIM_EXP(exp=e) then - match e - case DAE.CREF(componentRef = cr) then '' - else '-1' - end match - case DAE.DIM_UNKNOWN(__) then '-1' - else '-1' -end testdimension; - template functionInitial(list startValueEquations, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation) ::= let eqPart = (startValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => @@ -11332,8 +11322,9 @@ template testDaeDimensionExp(Exp exp) "Generates code for an expression." ::= match exp - case e as ICONST(__) then '' - else '-1' + case ICONST(integer=-1) then '---' // unknown + case ICONST(__) then '' // known static + else '-1' // known dynamic end testDaeDimensionExp; template daeDimension(DAE.Dimension dim, Context context, Text &preExp, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName, Boolean useFlatArrayNotation) diff --git a/OMCompiler/Compiler/Template/CodegenCppOld.tpl b/OMCompiler/Compiler/Template/CodegenCppOld.tpl index 2463cf69edb..b9aec7af802 100644 --- a/OMCompiler/Compiler/Template/CodegenCppOld.tpl +++ b/OMCompiler/Compiler/Template/CodegenCppOld.tpl @@ -5317,14 +5317,16 @@ match var */ case var as VARIABLE(__) then let marker = '<%contextCref(var.name,contextFunction,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)%>' - let &varInits += '/* varOutputTuple varInits(<%marker%>) */ <%\n%>' - let &varAssign += '// varOutput varAssign(<%marker%>) <%\n%>' + let &varInits += '// varOutputTuple varInits(<%marker%>)<%\n%>' + let &varAssign += '// varOutput varAssign(<%marker%>)<%\n%>' + let testinstDimsInit = (instDims |> dim => testDaeDimension(dim);separator="") let instDimsInit = (instDims |> dim => daeDimension(dim, contextFunction, &varInits, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation) ;separator=",") let assginBegin = 'get<<%ix%>>' if instDims then - let &varInits += '<%assginBegin%>(/*_<%fname%>*/output.data).setDims(<%instDimsInit%>);//todo setDims not for stat arrays - <%\n%>' + // don't setDims for static or unknown dimensions, treated as "" and "---", respectively + let &varInits += if boolAnd(intGt(stringLength(testinstDimsInit), 0), intEq(-1, stringFind(testinstDimsInit, "---"))) then + '<%assginBegin%>(/*_<%fname%>*/output.data).setDims(<%instDimsInit%>);<%\n%>' let &varAssign += '<%assginBegin%>(/*_<%fname%>*/output.data)=<%contextCref(var.name,contextFunction,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace,stateDerVectorName,useFlatArrayNotation)%>;<%\n%>' "" else @@ -5454,13 +5456,16 @@ template recordMemberInit(Var v, Text varName, Text &preExp /*BUFP*/, Text &varD end recordMemberInit; template setDims(Text testinstDimsInit, String varName , Text &varInits, String instDimsInit) + "call varName.setDims for dynamic and known dimensions" ::= match testinstDimsInit - case "" then let &varInits += '' + case "" then "" - else let &varInits += '<%varName%>.setDims(<%instDimsInit%>);<%\n%>' + else + let &varInits += if intEq(-1, stringFind(testinstDimsInit, "---")) then + '<%varName%>.setDims(<%instDimsInit%>);<%\n%>' "" - end match + end match end setDims; @@ -5626,8 +5631,8 @@ case var as VARIABLE(__) then let &varInits = buffer "" let testinstDimsInit = (instDims |> dim => testDaeDimension(dim);separator="") let instDimsInit = (instDims |> dim => daeDimension(dim, contextFunction, &varInits, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation);separator=",") - // check for unknown dimension that is treated as -1 - if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(instDimsInit, "-"))) then + // check for static and known dimension + if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(testinstDimsInit, "---"))) then if instDims then 'StatArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>, <%instDimsInit%>>& ' else expTypeFlag(var.ty, 5) else if instDims then 'DynArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>>/*<%instDimsInit%>*/&' else expTypeFlag(var.ty, 5) @@ -5641,8 +5646,8 @@ case var as VARIABLE(__) then let &varInits = buffer "" // should be empty let testinstDimsInit = (instDims |> dim => testDaeDimension(dim);separator="") let instDimsInit = (instDims |> dim => daeDimension(dim, contextFunction, &varInits, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, "stateDerVectorName_not_given", false /*is false the default?*/);separator=",") - // check for unknown dimension that is treated as -1 - if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(instDimsInit, "-"))) then + // check for static and known dimension + if boolAnd(stringEq(testinstDimsInit, ""), intEq(-1, stringFind(testinstDimsInit, "---"))) then if instDims then 'StatArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>, <%instDimsInit%>> ' else expTypeArrayIf(var.ty) else if instDims then 'DynArrayDim<%listLength(instDims)%><<%expTypeShort(var.ty)%>>/*<%instDimsInit%>*/ ' else expTypeArrayIf(var.ty) @@ -9558,21 +9563,6 @@ bool <%lastIdentOfPath(modelInfo.name)%>::isODE() >> end isODE; -template testdimension(Dimension d) -::= - match d - case DAE.DIM_BOOLEAN(__) then '' - case DAE.DIM_INTEGER(__) then '' - case DAE.DIM_ENUM(__) then '' - case DAE.DIM_EXP(exp=e) then - match e - case DAE.CREF(componentRef = cr) then '' - else '-1' - end match - case DAE.DIM_UNKNOWN(__) then '-1' - else '-1' -end testdimension; - template functionInitial(list startValueEquations, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation) ::= let eqPart = (startValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => @@ -11549,8 +11539,9 @@ template testDaeDimensionExp(Exp exp) "Generates code for an expression." ::= match exp - case e as ICONST(__) then '' - else '-1' + case ICONST(integer=-1) then '---' // unknown + case ICONST(__) then '' // known static + else '-1' // known dynamic end testDaeDimensionExp; template daeDimension(DAE.Dimension dim, Context context, Text &preExp, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName, Boolean useFlatArrayNotation) diff --git a/OMCompiler/SimulationRuntime/cpp/Core/Math/ArrayOperations.cpp b/OMCompiler/SimulationRuntime/cpp/Core/Math/ArrayOperations.cpp index 80e95121a6b..13569049d00 100644 --- a/OMCompiler/SimulationRuntime/cpp/Core/Math/ArrayOperations.cpp +++ b/OMCompiler/SimulationRuntime/cpp/Core/Math/ArrayOperations.cpp @@ -519,9 +519,8 @@ scalar product of two arrays (a,b type as template parameter) template T dot_array(const BaseArray& a, const BaseArray& b) { - if(a.getNumDims() != 1 || b.getNumDims() != 1) - throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,"error in dot array function. Wrong dimension"); - + if (a.getNumDims() != 1 || b.getNumDims() != 1) + throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "error in dot array function. Wrong dimension"); const T* data1 = a.getData(); const T* data2 = b.getData(); T r = std::inner_product(data1, data1 + a.getNumElems(), data2, 0.0); @@ -540,10 +539,13 @@ void cross_array(const BaseArray& a, const BaseArray& b, BaseArray& res }; /** -finds min/max elements of an array */ +finds min/max elements of an array +*/ template std::pair min_max(const BaseArray& x) { + if (x.getNumElems() < 1) + throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "min/max requires at least one element"); const T* data = x.getData(); std::pair ret = minmax_element(data, data + x.getNumElems());