Skip to content

Commit 9160007

Browse files
committed
FMI2 Cpp: introduce new getters and setters
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@25337 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
1 parent 80a062f commit 9160007

File tree

3 files changed

+198
-45
lines changed

3 files changed

+198
-45
lines changed

Compiler/Template/CodegenFMUCpp.tpl

Lines changed: 170 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ case SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
6464
let &extraFuncs = buffer "" /*BUFD*/
6565
let &extraFuncsDecl = buffer "" /*BUFD*/
6666
let cpp = CodegenCpp.translateModel(simCode)
67-
let()= textFile(fmuModelWrapperFile(simCode, extraFuncs, extraFuncsDecl, "",guid, FMUVersion), 'OMCpp<%fileNamePrefix%>FMU.cpp')
67+
let()= textFile(fmuModelHeaderFile(simCode, extraFuncs, extraFuncsDecl, "",guid, FMUVersion), 'OMCpp<%fileNamePrefix%>FMU.h')
68+
let()= textFile(fmuModelCppFile(simCode, extraFuncs, extraFuncsDecl, "",guid, FMUVersion), 'OMCpp<%fileNamePrefix%>FMU.cpp')
6869
let()= textFile(fmuModelDescriptionFileCpp(simCode, extraFuncs, extraFuncsDecl, "", guid, FMUVersion, FMUType), 'modelDescription.xml')
6970
let()= textFile(fmudeffile(simCode, FMUVersion), '<%fileNamePrefix%>.def')
7071
let()= textFile(fmuMakefile(target,simCode, extraFuncs, extraFuncsDecl, "", FMUVersion), '<%fileNamePrefix%>_FMU.makefile')
@@ -135,17 +136,51 @@ case SIMCODE(modelInfo = MODELINFO(varInfo = vi as VARINFO(__), vars = SIMVARS(s
135136
>>
136137
end fmiModelDescriptionAttributesCpp;
137138

138-
template fmuModelWrapperFile(SimCode simCode,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, String guid, String FMUVersion)
139-
"Generates code for ModelDescription file for FMU target."
139+
template fmuModelHeaderFile(SimCode simCode,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, String guid, String FMUVersion)
140+
"Generates declaration for FMU target."
141+
::=
142+
match simCode
143+
case SIMCODE(modelInfo=MODELINFO(__)) then
144+
let modelIdentifier = lastIdentOfPath(modelInfo.name)
145+
//let modelIdentifier = System.stringReplace(dotPath(modelInfo.name), ".", "_")
146+
<<
147+
// declaration for Cpp FMU target
148+
#include "OMCpp<%fileNamePrefix%>Extension.h"
149+
150+
class <%modelIdentifier%>FMU: public <%modelIdentifier%>Extension {
151+
public:
152+
// constructor
153+
<%modelIdentifier%>FMU(IGlobalSettings* globalSettings,
154+
boost::shared_ptr<IAlgLoopSolverFactory> nonLinSolverFactory,
155+
boost::shared_ptr<ISimData> simData);
156+
157+
// getters for given value references
158+
virtual void getReal(const unsigned int vr[], int nvr, double value[]);
159+
virtual void getInteger(const unsigned int vr[], int nvr, int value[]);
160+
virtual void getBoolean(const unsigned int vr[], int nvr, int value[]);
161+
virtual void getString(const unsigned int vr[], int nvr, string value[]);
162+
163+
// setters for given value references
164+
virtual void setReal(const unsigned int vr[], int nvr, const double value[]);
165+
virtual void setInteger(const unsigned int vr[], int nvr, const int value[]);
166+
virtual void setBoolean(const unsigned int vr[], int nvr, const int value[]);
167+
virtual void setString(const unsigned int vr[], int nvr, const string value[]);
168+
};
169+
>>
170+
end fmuModelHeaderFile;
171+
172+
template fmuModelCppFile(SimCode simCode,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, String guid, String FMUVersion)
173+
"Generates code for FMU target."
140174
::=
141175
match simCode
142176
case SIMCODE(modelInfo=MODELINFO(__)) then
143177
let modelName = dotPath(modelInfo.name)
144178
let modelShortName = lastIdentOfPath(modelInfo.name)
145-
let modelIdentifier = System.stringReplace(modelName, ".", "_")
179+
//let modelIdentifier = System.stringReplace(modelName, ".", "_")
180+
let modelIdentifier = modelShortName
146181
<<
147182
// define model identifier and unique id
148-
#define MODEL_IDENTIFIER <%modelShortName%>
183+
#define MODEL_IDENTIFIER <%modelIdentifier%>
149184
#define MODEL_GUID "{<%guid%>}"
150185

151186
#include <Core/Modelica.h>
@@ -158,7 +193,7 @@ case SIMCODE(modelInfo=MODELINFO(__)) then
158193
#include <Solver/IAlgLoopSolver.h>
159194
#include <System/IAlgLoopSolverFactory.h>
160195
#include <SimController/ISimData.h>
161-
#include "OMCpp<%fileNamePrefix%>Extension.h"
196+
#include "OMCpp<%fileNamePrefix%>FMU.h"
162197

163198
<%ModelDefineData(modelInfo)%>
164199
#define NUMBER_OF_EVENT_INDICATORS <%zerocrosslength(simCode, extraFuncs ,extraFuncsDecl, extraFuncsNamespace)%>
@@ -167,20 +202,30 @@ case SIMCODE(modelInfo=MODELINFO(__)) then
167202
'#include "FMU2/FMU2Wrapper.cpp"'
168203
else
169204
'#include "FMU/FMUWrapper.cpp"'%>
170-
171205
<%if isFMIVersion20(FMUVersion) then
172206
'#include "FMU2/FMU2Interface.cpp"'
173207
else
174208
'#include "FMU/FMULibInterface.cpp"'%>
175209

176-
#if 0
177-
<%setDefaultStartValues(modelInfo)%>
178-
<%setStartValues(modelInfo)%>
179-
<%setExternalFunction(modelInfo)%>
180-
#endif
210+
// constructor
211+
<%modelIdentifier%>FMU::<%modelIdentifier%>FMU(IGlobalSettings* globalSettings,
212+
boost::shared_ptr<IAlgLoopSolverFactory> nonLinSolverFactory,
213+
boost::shared_ptr<ISimData> simData):
214+
PreVariables(<%getPreVarsCount(simCode)%>),
215+
<%modelIdentifier%>(globalSettings, nonLinSolverFactory, simData),
216+
<%modelIdentifier%>Extension(globalSettings, nonLinSolverFactory, simData) {
217+
}
181218

219+
// getters
220+
<%accessFunctions(simCode, "get", modelIdentifier, modelInfo)%>
221+
// setters
222+
<%accessFunctions(simCode, "set", modelIdentifier, modelInfo)%>
182223
>>
183-
end fmuModelWrapperFile;
224+
// TODO:
225+
// <%setDefaultStartValues(modelInfo)%>
226+
// <%setStartValues(modelInfo)%>
227+
// <%setExternalFunction(modelInfo)%>
228+
end fmuModelCppFile;
184229

185230
template ModelDefineData(ModelInfo modelInfo)
186231
"Generates global data in simulation file."
@@ -371,6 +416,118 @@ template setExternalFunctionSwitch(Function fn)
371416
>>
372417
end setExternalFunctionSwitch;
373418

419+
template accessFunctions(SimCode simCode, String direction, String modelIdentifier, ModelInfo modelInfo)
420+
"Generates getters and setters for Real, Integer, Boolean, and String."
421+
::=
422+
match modelInfo
423+
case MODELINFO(vars=SIMVARS(__)) then
424+
<<
425+
<%accessRealFunction(simCode, direction, modelIdentifier, modelInfo)%>
426+
<%accessVarsFunction(simCode, direction, modelIdentifier, "Integer", "int", vars.intAlgVars, vars.intParamVars, vars.intAliasVars)%>
427+
<%accessVarsFunction(simCode, direction, modelIdentifier, "Boolean", "int", vars.boolAlgVars, vars.boolParamVars, vars.boolAliasVars)%>
428+
<%accessVarsFunction(simCode, direction, modelIdentifier, "String", "string", vars.stringAlgVars, vars.stringParamVars, vars.stringAliasVars)%>
429+
>>
430+
end accessFunctions;
431+
432+
template accessRealFunction(SimCode simCode, String direction, String modelIdentifier, ModelInfo modelInfo)
433+
"Generates getReal and setReal functions."
434+
::=
435+
match modelInfo
436+
case MODELINFO(vars=SIMVARS(__), varInfo=VARINFO(numStateVars=numStateVars, numAlgVars=numAlgVars, numDiscreteReal=numDiscreteReal, numParams=numParams)) then
437+
let qualifier = if stringEq(direction, "set") then "const"
438+
let statesOffset = intMul(2, stringInt(numFMUStateVars(vars.stateVars)))
439+
<<
440+
void <%modelIdentifier%>FMU::<%direction%>Real(const unsigned int vr[], int nvr, <%qualifier%> double value[]) {
441+
for (int i = 0; i < nvr; i++)
442+
switch (vr[i]) {
443+
<%vars.stateVars |> var => accessVecVar(direction, var, 0, "__z"); separator="\n"%>
444+
<%vars.derivativeVars |> var => accessVecVar(direction, var, numStateVars, "__zDot"); separator="\n"%>
445+
<%accessVars(simCode, direction, vars.algVars, stringInt(statesOffset))%>
446+
<%accessVars(simCode, direction, vars.discreteAlgVars, intAdd(stringInt(statesOffset), numAlgVars))%>
447+
<%accessVars(simCode, direction, vars.paramVars, intAdd(intAdd(stringInt(statesOffset), numAlgVars), numDiscreteReal))%>
448+
<%accessVars(simCode, direction, vars.aliasVars, intAdd(intAdd(intAdd(stringInt(statesOffset), numAlgVars), numDiscreteReal), numParams))%>
449+
default:
450+
std::ostringstream message;
451+
message << "<%direction%>Real with wrong value reference " << vr[i];
452+
throw std::invalid_argument(message.str());
453+
}
454+
}
455+
456+
>>
457+
end accessRealFunction;
458+
459+
template numFMUStateVars(list<SimVar> stateVars)
460+
"Return number of states without dummy state"
461+
::=
462+
if intGt(listLength(stateVars), 1) then listLength(stateVars) else (stateVars |> var => match var case SIMVAR(__) then if stringEq(crefStr(name), "$dummy") then 0 else 1)
463+
end numFMUStateVars;
464+
465+
template accessVarsFunction(SimCode simCode, String direction, String modelIdentifier, String typeName, String typeImpl, list<SimVar> algVars, list<SimVar> paramVars, list<SimVar> aliasVars)
466+
"Generates get<%typeName%> and set<%typeName%> functions."
467+
::=
468+
let qualifier = if stringEq(direction, "set") then "const"
469+
<<
470+
void <%modelIdentifier%>FMU::<%direction%><%typeName%>(const unsigned int vr[], int nvr, <%qualifier%> <%typeImpl%> value[]) {
471+
for (int i = 0; i < nvr; i++)
472+
switch (vr[i]) {
473+
<%accessVars(simCode, direction, algVars, 0)%>
474+
<%accessVars(simCode, direction, paramVars, listLength(algVars))%>
475+
<%accessVars(simCode, direction, aliasVars, intAdd(listLength(algVars), listLength(paramVars)))%>
476+
default:
477+
std::ostringstream message;
478+
message << "<%direction%><%typeName%> with wrong value reference " << vr[i];
479+
throw std::invalid_argument(message.str());
480+
}
481+
}
482+
483+
>>
484+
end accessVarsFunction;
485+
486+
template accessVars(SimCode simCode, String direction, list<SimVar> varsList, Integer offset)
487+
"Generates list of case statements in get functions of Cpp file."
488+
::=
489+
<<
490+
<%varsList |> var => accessVar(simCode, direction, var, offset); separator="\n"%>
491+
>>
492+
end accessVars;
493+
494+
template accessVar(SimCode simCode, String direction, SimVar simVar, Integer offset)
495+
"Generates code for accessing variables in Cpp file for FMU target."
496+
::=
497+
match simVar
498+
case SIMVAR(__) then
499+
let description = if comment then '// <%comment%>'
500+
let varname = cref1(name, simCode, "", "", "", contextOther, "", "", false)
501+
if stringEq(direction, "get") then
502+
<<
503+
case <%intAdd(offset, index)%>: value[i] = <%varname%>; break; <%description%>
504+
>>
505+
else
506+
<<
507+
case <%intAdd(offset, index)%>: <%varname%> = value[i]; break; <%description%>
508+
>>
509+
end accessVar;
510+
511+
template accessVecVar(String direction, SimVar simVar, Integer offset, String vecName)
512+
"Generates code for accessing vector variables, neglecting $dummy states."
513+
::=
514+
match simVar
515+
case SIMVAR(__) then
516+
let description = if comment then '// <%comment%>'
517+
if stringEq(crefStr(name), "$dummy") then
518+
<<>>
519+
else if stringEq(crefStr(name), "der($dummy)") then
520+
<<>>
521+
else if stringEq(direction, "get") then
522+
<<
523+
case <%intAdd(offset, index)%>: value[i] = <%vecName%>[<%index%>]; break; <%description%>
524+
>>
525+
else
526+
<<
527+
case <%intAdd(offset, index)%>: <%vecName%>[<%index%>] = value[i]; break; <%description%>
528+
>>
529+
end accessVecVar;
530+
374531
template getPlatformString2(String platform, String fileNamePrefix, String dirExtra, String libsPos1, String libsPos2, String omhome)
375532
"returns compilation commands for the platform. "
376533
::=

SimulationRuntime/cpp/Include/FMU2/FMU2Wrapper.cpp

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ FMU2Wrapper::FMU2Wrapper(fmi2String instanceName, fmi2String GUID,
7979
boost::shared_ptr<ISimData>(new SimData())));
8080
_model->setInitial(true);
8181
_model->initialize(); // set default start values
82-
_tmp_real_buffer.resize(_model->getDimReal());
83-
_tmp_int_buffer.resize(_model->getDimInteger());
84-
_tmp_bool_buffer.resize(_model->getDimBoolean());
82+
_string_buffer.resize(_model->getDimString());
8583
}
8684

8785
FMU2Wrapper::~FMU2Wrapper()
@@ -189,40 +187,39 @@ fmi2Status FMU2Wrapper::completedIntegratorStep(fmi2Boolean noSetFMUStatePriorTo
189187
fmi2Status FMU2Wrapper::setReal(const fmi2ValueReference vr[], size_t nvr,
190188
const fmi2Real value[])
191189
{
192-
_model->getReal(&_tmp_real_buffer[0]);
193-
for(size_t i = 0; i < nvr; ++i)
194-
_tmp_real_buffer[vr[i]] = value[i];
195-
_model->setReal(&_tmp_real_buffer[0]);
190+
_model->setReal(vr, nvr, value);
196191
_need_update = true;
197192
return fmi2OK;
198193
}
199194

200195
fmi2Status FMU2Wrapper::setInteger(const fmi2ValueReference vr[], size_t nvr,
201196
const fmi2Integer value[])
202197
{
203-
_model->getInteger(&_tmp_int_buffer[0]);
204-
for(size_t i = 0; i < nvr; ++i)
205-
_tmp_int_buffer[vr[i]] = value[i];
206-
_model->setInteger(&_tmp_int_buffer[0]);
198+
_model->setInteger(vr, nvr, value);
207199
_need_update = true;
208200
return fmi2OK;
209201
}
210202

211203
fmi2Status FMU2Wrapper::setBoolean(const fmi2ValueReference vr[], size_t nvr,
212204
const fmi2Boolean value[])
213205
{
214-
_model->getBoolean((bool*) &_tmp_bool_buffer[0]);
215-
for(size_t i = 0; i < nvr; ++i)
216-
_tmp_bool_buffer[vr[i]] = value[i];
217-
_model->setBoolean((bool*) &_tmp_bool_buffer[0]);
206+
_model->setBoolean(vr, nvr, value);
218207
_need_update = true;
219208
return fmi2OK;
220209
}
221210

222211
fmi2Status FMU2Wrapper::setString(const fmi2ValueReference vr[], size_t nvr,
223212
const fmi2String value[])
224213
{
225-
// TODO implement strings
214+
if (nvr > _string_buffer.size()) {
215+
FMU2_LOG(this, fmi2Error, logStatusError,
216+
"Attempt to set %d fmi2String; FMU only has %d",
217+
nvr, _string_buffer.size());
218+
return fmi2Error;
219+
}
220+
for (size_t i = 0; i < nvr; i++)
221+
_string_buffer[i] = string(value[i]); // convert to string
222+
_model->setString(vr, nvr, &_string_buffer[0]);
226223
_need_update = true;
227224
return fmi2OK;
228225
}
@@ -264,43 +261,44 @@ fmi2Status FMU2Wrapper::getEventIndicators(fmi2Real eventIndicators[], size_t ni
264261
return fmi2OK;
265262
}
266263

267-
// Funktions for reading the values of variables that have a reference by the modelDescription.xml
264+
// Functions for reading the values of variables
268265
fmi2Status FMU2Wrapper::getReal(const fmi2ValueReference vr[], size_t nvr,
269266
fmi2Real value[])
270267
{
271268
updateModel();
272-
_model->getReal(&_tmp_real_buffer[0]);
273-
for(size_t i = 0; i < nvr; ++i)
274-
value[i] = _tmp_real_buffer[vr[i]];
269+
_model->getReal(vr, nvr, value);
275270
return fmi2OK;
276271
}
277272

278273
fmi2Status FMU2Wrapper::getInteger(const fmi2ValueReference vr[], size_t nvr,
279274
fmi2Integer value[])
280275
{
281276
updateModel();
282-
_model->getInteger(&_tmp_int_buffer[0]);
283-
for(size_t i = 0; i < nvr; ++i)
284-
value[i] = _tmp_int_buffer[vr[i]];
277+
_model->getInteger(vr, nvr, value);
285278
return fmi2OK;
286279
}
287280

288281
fmi2Status FMU2Wrapper::getBoolean(const fmi2ValueReference vr[], size_t nvr,
289282
fmi2Boolean value[])
290283
{
291284
updateModel();
292-
_model->getBoolean((bool*) &_tmp_bool_buffer[0]);
293-
for(size_t i = 0; i < nvr; ++i)
294-
value[i] = _tmp_bool_buffer[vr[i]];
285+
_model->getBoolean(vr, nvr, value);
295286
return fmi2OK;
296287
}
297288

298289
fmi2Status FMU2Wrapper::getString(const fmi2ValueReference vr[], size_t nvr,
299290
fmi2String value[])
300291
{
292+
if (nvr > _string_buffer.size()) {
293+
FMU2_LOG(this, fmi2Error, logStatusError,
294+
"Attempt to get %d fmi2String; FMU only has %d",
295+
nvr, _string_buffer.size());
296+
return fmi2Error;
297+
}
301298
updateModel();
302-
// for(size_t i = 0; i < nvr; ++i)
303-
//TODO _model->getString(vr[i], value[i]);
299+
_model->getString(vr, nvr, &_string_buffer[0]);
300+
for (size_t i = 0; i < nvr; i++)
301+
value[i] = _string_buffer[i].c_str(); // convert to fmi2String
304302
return fmi2OK;
305303
}
306304

SimulationRuntime/cpp/Include/FMU2/FMU2Wrapper.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
// build MODEL_CLASS from MODEL_IDENTIFIER
4444
#define FMU2_PASTER(a, b) a ## b
4545
#define FMU2_CONCAT(a, b) FMU2_PASTER(a, b)
46-
#define MODEL_CLASS FMU2_CONCAT(MODEL_IDENTIFIER, Extension)
46+
#define MODEL_CLASS FMU2_CONCAT(MODEL_IDENTIFIER, FMU)
4747

4848
// define logger as macro that passes through variadic args
4949
#define FMU2_LOG(w, status, category, ...) \
@@ -130,9 +130,7 @@ class FMU2Wrapper
130130
private:
131131
FMU2GlobalSettings _global_settings;
132132
boost::shared_ptr<MODEL_CLASS> _model;
133-
std::vector<fmi2Real> _tmp_real_buffer;
134-
std::vector<fmi2Integer> _tmp_int_buffer;
135-
std::vector<fmi2Boolean> _tmp_bool_buffer;
133+
std::vector<string> _string_buffer;
136134
double _need_update;
137135
void updateModel();
138136

0 commit comments

Comments
 (0)