Skip to content

Commit

Permalink
Add support for pre of arrays to Cpp runtime (#7574)
Browse files Browse the repository at this point in the history
* Add support for pre of arrays to Cpp runtime

DiscreteEvents/SimVars:
 - add pre of arrays

Array:
 - add new WrapArray for array return value from pre

FactoryConfig:
  - remove interface includes to avoid additional include of Array.h

CodegenCppCommon:
 - move $PRE qualifier for lhs from contextCref to cref1
 - make BaseArray function call arguments const

* Distinguish lhs from rhs daeExpCref and add test

This is needed for the appropriate treatment of ArraySlice/Const after
the introduction of const qualifiers for BaseArray refs in d3085da.
  • Loading branch information
rfranke committed Jun 18, 2021
1 parent 9280895 commit 7a4ad0e
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 51 deletions.
26 changes: 13 additions & 13 deletions OMCompiler/Compiler/Template/CodegenCppCommonOld.tpl
Expand Up @@ -148,10 +148,6 @@ end subscriptStr;
template contextCref(ComponentRef cr, Context context,SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
"Generates code for a component reference depending on which context we're in."
::=
match cr
case CREF_QUAL(ident = "$PRE") then
'_discrete_events->pre(<%contextCref(componentRef,context,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)%>)'
else
let &varDeclsCref = buffer "" /*BUFD*/
match context
case FUNCTION_CONTEXT(__) then crefStr(cr)
Expand Down Expand Up @@ -212,7 +208,10 @@ end crefToCStrWithIndex;

template cref1(ComponentRef cr, SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, Context context, Text &varDecls, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation) ::=
match cr
case CREF_IDENT(ident = "xloc") then '<%representationCref(cr, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, context, varDecls, stateDerVectorName, useFlatArrayNotation)%>'
case CREF_QUAL(ident = "$PRE") then
'_discrete_events->pre(<%cref1(componentRef, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, context, varDecls, stateDerVectorName, useFlatArrayNotation)%>)'
case CREF_IDENT(ident = "xloc") then
'<%representationCref(cr, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, context, varDecls, stateDerVectorName, useFlatArrayNotation)%>'
case CREF_IDENT(ident = "time") then
match context
case ALGLOOP_CONTEXT(genInitialisation=false)
Expand Down Expand Up @@ -350,20 +349,20 @@ template daeExpCrefRhs(Exp exp, Context context, Text &preExp, Text &varDecls, S
// by daeExpRecordCrefRhs only in a simulation context, not in a function.
case CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = RECORD(path = _))) then
match context case FUNCTION_CONTEXT(__) then
'<%daeExpCrefRhs2(exp, context, &preExp, &varDecls,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)%>'
'<%daeExpCref(false, exp, context, &preExp, &varDecls,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)%>'
else
daeExpRecordCrefRhs(t, cr, context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
case CREF(ty = T_FUNCTION_REFERENCE_FUNC(functionType=t)) then
functionClosure(underscorePath(crefToPathIgnoreSubs(componentRef)), "", t, t, context, &extraFuncsDecl)
case CREF(componentRef = CREF_IDENT(ident=ident), ty = T_FUNCTION_REFERENCE_VAR(__)) then
contextFunName(ident, context)
else
daeExpCrefRhs2(exp, context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
daeExpCref(false, exp, context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
end daeExpCrefRhs;


template daeExpCrefRhs2(Exp ecr, Context context, Text &preExp, Text &varDecls, SimCode simCode, Text& extraFuncs,
Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
template daeExpCref(Boolean isLhs, Exp ecr, Context context, Text &preExp, Text &varDecls, SimCode simCode, Text& extraFuncs,
Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
"Generates code for a component reference."
::=
match ecr
Expand Down Expand Up @@ -391,13 +390,14 @@ case component as CREF(componentRef=cr, ty=ty) then
else
// The array subscript denotes a slice
let arrName = contextArrayCref(cr, context)
let typeStr = expTypeShort(ty)
let arrTypeStr = if isLhs then 'ArraySlice' else 'ArraySliceConst'
let elTypeStr = expTypeShort(ty)
let slice = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp,
&varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace,
stateDerVectorName, useFlatArrayNotation)
let &preExp += 'ArraySlice<<%typeStr%>> <%slice%>_as(<%arrName%>, <%slice%>);<%\n%>'
let &preExp += '<%arrTypeStr%><<%elTypeStr%>> <%slice%>_as(<%arrName%>, <%slice%>);<%\n%>'
'<%slice%>_as'
end daeExpCrefRhs2;
end daeExpCref;


template daeExpCrefIndexSpec(list<Subscript> subs, Context context,
Expand Down Expand Up @@ -745,7 +745,7 @@ template expTypeFlag(DAE.Type ty, Integer flag)

case 8 then
match ty
case T_ARRAY(dims=dims) then'BaseArray<<%expTypeShort(ty)%>>&'
case T_ARRAY(dims=dims) then 'const BaseArray<<%expTypeShort(ty)%>>&'
else expTypeFlag(ty, 9)
end match

Expand Down
4 changes: 2 additions & 2 deletions OMCompiler/Compiler/Template/CodegenCppOld.tpl
Expand Up @@ -11557,7 +11557,7 @@ template equationForLoop(SimEqSystem eq, Context context, Text &varDecls, SimCod
let startExp = daeExp(startIt, context, preExp, varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, false)
let endExp = daeExp(endIt, context, preExp, varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, false)
let expPart = daeExp(exp, context, preExp, varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, false)
let crefPart = daeExp(crefExp(cref), context, preExp, varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, false)
let crefPart = daeExpCref(true, crefExp(cref), context, preExp, varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, false)
<<
<%if not assignToStartValues then '<%startFixedExp%>'%>
for (int <%iterExp%> = <%startExp%>; <%iterExp%> <= <%endExp%>; <%iterExp%>++) {
Expand Down Expand Up @@ -13650,7 +13650,7 @@ match stmt
case STMT_ASSIGN_ARR(exp=e, lhs=lhsexp as CREF(componentRef=cr), type_=t) then
let &preExp = buffer "" /*BUFD*/
let expPart = daeExp(e, context, &preExp /*BUFC*/, &varDecls /*BUFD*/, simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
let dest = daeExp(lhsexp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/, simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
let dest = daeExpCref(true, lhsexp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/, simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
<<
<%preExp%>
<%dest%>.assign(<%expPart%>);
Expand Down
24 changes: 24 additions & 0 deletions OMCompiler/SimulationRuntime/cpp/Core/System/SimVars.cpp
Expand Up @@ -492,6 +492,30 @@ std::string& SimVars::getPreVar(const std::string& var)
return _pre_string_vars[i];
}

WrapArray<double> SimVars::getPreArr(const BaseArray<double>& arr)
{
size_t i = arr.getData() - _real_vars;
return WrapArray<double>(_pre_real_vars + i, arr.getNumElems());
}

WrapArray<int> SimVars::getPreArr(const BaseArray<int>& arr)
{
size_t i = arr.getData() - _int_vars;
return WrapArray<int>(_pre_int_vars + i, arr.getNumElems());
}

WrapArray<bool> SimVars::getPreArr(const BaseArray<bool>& arr)
{
size_t i = arr.getData() - _bool_vars;
return WrapArray<bool>(_pre_bool_vars + i, arr.getNumElems());
}

WrapArray<std::string> SimVars::getPreArr(const BaseArray<std::string>& arr)
{
size_t i = arr.getData() - _string_vars;
return WrapArray<std::string>(_pre_string_vars + i, arr.getNumElems());
}

/**\brief returns a pointer to a real simvar variable in simvar array
* \param [in] i index of simvar in simvar array
* \return pointer to simvar
Expand Down
178 changes: 178 additions & 0 deletions OMCompiler/SimulationRuntime/cpp/Include/Core/Math/Array.h
Expand Up @@ -629,6 +629,184 @@ class RefArrayDim3 : public RefArray<T, size1*size2*size3>
}
};

/**
* Wrap external data with nelems unknown at compile time into array, implements BaseArray interface methods
* @param T type of the array elements
*/
template<typename T>
class WrapArray : public BaseArray<T>
{
public:
/**
* Constuctor for wrapper array storing a pointer
*/
WrapArray(T* data, size_t nelems)
:BaseArray<T>(true, false)
{
_data = data;
_nelems = nelems;
}

/**
* Constuctor for wrapper array that
* holds a pointer to otherarray's data
*/
WrapArray(const WrapArray<T>& otherarray)
:BaseArray<T>(true, false)
{
_data = otherarray._data;
_nelems = otherarray.getNumElems();
}

/**
* Default constuctor for wrapper array
*/
WrapArray()
:BaseArray<T>(true, false)
{
_data = NULL; // no data assigned yet
_nelems = 0;
}

virtual ~WrapArray() {}

/**
* Index operator to read array element
* @param idx vector of indices
*/
virtual const T& operator()(const vector<size_t>& idx) const
{
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "Wrong WrapArray const operator() call");
}

/**
* Index operator to write array element
* @param idx vector of indices
*/
virtual T& operator()(const vector<size_t>& idx)
{
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "Wrong WrapArray operator() call");
}

/**
* Return sizes of dimensions
*/
virtual std::vector<size_t> getDims() const
{
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "Wrong WrapArray getDims call");
}

/**
* Return sizes of one dimension
*/
virtual int getDim(size_t dim) const
{
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "Wrong WrapArray getDim call");
}

/**
* Returns number of dimensions
*/
virtual size_t getNumDims() const
{
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, "Wrong WrapArray getNumDims call");
}

/**
* Resize array method
* @param dims vector with new dimension sizes
* wrapper array could not be resized
*/
virtual void resize(const std::vector<size_t>& dims)
{
if (dims != this->getDims())
throw std::runtime_error("Cannot resize wrapper array!");
}

/**
* Assigns data to array
* @param data new array data
* a.assign(data)
*/
virtual void assign(const T* data)
{
if (_nelems > 0) {
if (_data == NULL)
throw std::runtime_error("Cannot assign data to uninitialized WrapArray!");
std::copy(data, data + _nelems, _data);
}
}

/**
* Assigns array data to array
* @param b any array of type BaseArray
* a.assign(b)
*/
virtual void assign(const BaseArray<T>& b)
{
if (_nelems > 0) {
if (_data == NULL)
throw std::runtime_error("Cannot assign to uninitialized WrapArray!");
assert(b.getNumElems() == _nelems);
b.getDataCopy(_data, _nelems);
}
}

/**
* Assigns value to each array element
* @param value new array value
* a.assign(value)
*/
virtual void assign(const T& value)
{
if (_nelems > 0) {
if (_data == NULL)
throw std::runtime_error("Cannot assign value to uninitialized WrapArray!");
std::fill(_data, _data + _nelems, value);
}
}

/**
* Access to data
*/
virtual T* getData()
{
return _data;
}

/**
* Access to data (read-only)
*/
virtual const T* getData() const
{
return _data;
}

/**
* Copies the array data of size n in the data array
* data has to be allocated before getDataCopy is called
*/
virtual void getDataCopy(T data[], size_t n) const
{
if (n > 0)
std::copy(_data, _data + n, data);
}

/**
* Returns number of elements
*/
virtual size_t getNumElems() const
{
return _nelems;
}

virtual void setDims(const std::vector<size_t>& v) {}

protected:
T *_data; // array data
size_t _nelems; // number of elements
};

/**
* Static array, implements BaseArray interface methods
* @param T type of the array
Expand Down
Expand Up @@ -30,6 +30,10 @@ class BOOST_EXTENSION_EVENTHANDLING_DECL DiscreteEvents
int& pre(const int& var);
bool& pre(const bool& var);
std::string& pre(const std::string& var);
template<typename T>
WrapArray<T> pre(const BaseArray<T>& arr) {
return _sim_vars->getPreArr(arr);
}
//Implementation of the Modelica edge operator
bool edge(double& var);
bool edge(int& var);
Expand Down
21 changes: 13 additions & 8 deletions OMCompiler/SimulationRuntime/cpp/Include/Core/System/ISimVars.h
Expand Up @@ -61,13 +61,18 @@ class ISimVars
virtual bool& initBoolVar(size_t i)= 0;
virtual string& initStringVar(size_t i)= 0;

/*Methods for pre- variables*/
virtual void savePreVariables() = 0;
virtual void initPreVariables()= 0;
/*access methods for pre-variable*/
virtual double& getPreVar(const double& var)=0;
virtual int& getPreVar(const int& var)=0;
virtual bool& getPreVar(const bool& var)=0;
virtual std::string& getPreVar(const std::string& var)=0;
/*Methods for pre- variables*/
virtual void savePreVariables() = 0;
virtual void initPreVariables() = 0;
/*access methods for pre-variable*/
virtual double& getPreVar(const double& var) = 0;
virtual int& getPreVar(const int& var) = 0;
virtual bool& getPreVar(const bool& var) = 0;
virtual std::string& getPreVar(const std::string& var) = 0;
/*access methods for pre-array*/
virtual WrapArray<double> getPreArr(const BaseArray<double>& arr) = 0;
virtual WrapArray<int> getPreArr(const BaseArray<int>& arr) = 0;
virtual WrapArray<bool> getPreArr(const BaseArray<bool>& arr) = 0;
virtual WrapArray<std::string> getPreArr(const BaseArray<std::string>& arr) = 0;
};
/** @} */ // end of coreSystem
Expand Up @@ -112,6 +112,10 @@ class BOOST_EXTENSION_SIMVARS_DECL SimVars: public ISimVars
virtual int& getPreVar(const int& var);
virtual bool& getPreVar(const bool& var);
virtual std::string& getPreVar(const std::string& var);
virtual WrapArray<double> getPreArr(const BaseArray<double>& arr);
virtual WrapArray<int> getPreArr(const BaseArray<int>& arr);
virtual WrapArray<bool> getPreArr(const BaseArray<bool>& arr);
virtual WrapArray<std::string> getPreArr(const BaseArray<std::string>& arr);

virtual size_t getDimString() const;
virtual size_t getDimBool() const;
Expand Down
Expand Up @@ -78,34 +78,6 @@
/*Defines*/
#define PATH string
#include "LibrariesConfig.h"
/*interface includes*/
#include <Core/System/ISystemProperties.h>
#include <Core/System/ISystemInitialization.h>
#include <Core/System/IWriteOutput.h>
#include <Core/System/IContinuous.h>
#include <Core/System/ITime.h>
#include <Core/System/IEvent.h>
#include <Core/System/IStepEvent.h>
#include <Core/Solver/INonLinSolverSettings.h>
#include <Core/Solver/ILinSolverSettings.h>
#include <Core/DataExchange/IHistory.h>
#include <Core/System/IMixedSystem.h>
#include <Core/SimulationSettings/IGlobalSettings.h>
#include <Core/System/ILinearAlgLoop.h>
#include <Core/System/INonLinearAlgLoop.h>
#include <Core/Solver/ISolverSettings.h>
#include <Core/Solver/ISolver.h>
#include <Core/Solver/ILinearAlgLoopSolver.h>
#include <Core/Solver/INonLinearAlgLoopSolver.h>
#include <Core/System/IAlgLoopSolverFactory.h>
#include <Core/System/ISimVars.h>
#include <Core/DataExchange/ISimVar.h>
#include <Core/SimController/ISimData.h>
#include <Core/SimController/ISimObjects.h>
#include <Core/SimulationSettings/ISimControllerSettings.h>
#include <Core/SimController/ISimController.h>



#else
#error "operating system not supported"
Expand Down

0 comments on commit 7a4ad0e

Please sign in to comment.