Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit e7c76f7

Browse files
rfrankeOpenModelica-Hudson
authored andcommitted
Introduce subactive evaluation mode for clocked equations
Subactive evaluation means that discrete states are kept constant while all other discrete variables are updated. This is useful for numerical analysis, like calculation of partial derivatives.
1 parent d316ab2 commit e7c76f7

File tree

6 files changed

+75
-59
lines changed

6 files changed

+75
-59
lines changed

Compiler/Template/CodegenCpp.tpl

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3959,11 +3959,11 @@ match simCode
39593959

39603960
void <%modelname%>Algloop<%ls.index%>::evaluate()
39613961
{
3962-
<%varDecls%>
3963-
//prebody
3964-
<%prebody%>
3965-
//body
3966-
<%body%>
3962+
<%varDecls%>
3963+
//prebody
3964+
<%prebody%>
3965+
//body
3966+
<%body%>
39673967
}
39683968
>>
39693969
else
@@ -4073,13 +4073,10 @@ case SIMCODE(modelInfo = MODELINFO(__)) then
40734073
functionExtraResidualsPreBody(eq2, &varDecls, context, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
40744074
;separator="\n")
40754075
let body = (nls.eqs |> eq2 as SES_RESIDUAL(__) hasindex i0 =>
4076-
let &preExp = buffer "" /*BUFD*/
4077-
let expPart = daeExp(eq2.exp, context, &preExp, &varDecls, simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
4078-
'<%preExp%>_res[<%i0%>] = <%expPart%>;'
4079-
4076+
let &preExp = buffer "" /*BUFD*/
4077+
let expPart = daeExp(eq2.exp, context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
4078+
'<%preExp%>_res[<%i0%>] = <%expPart%>;'
40804079
;separator="\n")
4081-
4082-
40834080
<<
40844081
<% match eq
40854082
case SES_NONLINEAR(nlSystem = nls as NONLINEARSYSTEM(__)) then
@@ -4088,13 +4085,12 @@ case SIMCODE(modelInfo = MODELINFO(__)) then
40884085
>>
40894086
%>
40904087
{
4091-
<%if intGt(clockIndex, 0) then 'const int clockIndex = <%clockIndex%>;'%>
4092-
<%varDecls%>
4093-
4094-
//prebody
4095-
<%prebody%>
4096-
//body
4097-
<%body%>
4088+
<%if intGt(clockIndex, 0) then 'const int clockIndex = <%clockIndex%>;'%>
4089+
<%varDecls%>
4090+
//prebody
4091+
<%prebody%>
4092+
//body
4093+
<%body%>
40984094
}
40994095
>>
41004096
end updateAlgloopNonLinear;
@@ -6391,12 +6387,11 @@ case SES_NONLINEAR(nlSystem = nls as NONLINEARSYSTEM(__)) then
63916387
'<%preExp%>_b[<%i0%>] = <%expPart%>;'
63926388
;separator="\n")
63936389
<<
6394-
6395-
<%varDecls%>
6396-
//prebody
6397-
<%prebody%>
6398-
//body
6399-
<%body%>
6390+
<%varDecls%>
6391+
//prebody
6392+
<%prebody%>
6393+
//body
6394+
<%body%>
64006395
>>
64016396
else
64026397
let &varDecls = buffer "" /*BUFD*/
@@ -9544,6 +9539,7 @@ case SIMCODE(modelInfo = MODELINFO(__), modelStructure = fmims) then
95449539
_clockShift[<%i%>] = <%snom%>.0 / <%sres%>.0;
95459540
_clockTime[<%i%>] = _simTime + _clockShift[<%i%>] * _clockInterval[<%i%>];
95469541
_clockStart[<%i%>] = true;
9542+
_clockSubactive[<%i%>] = false;
95479543
<%i%> ++;
95489544
>>
95499545
; separator="\n")
@@ -11327,8 +11323,8 @@ match eq
1132711323
case SES_SIMPLE_ASSIGN(__) then
1132811324
let &preExp = buffer "" /*BUFD*/
1132911325
let startFixedExp = match cref2simvar(cref, simCode)
11330-
case SIMVAR(varKind = CLOCKED_STATE(isStartFixed = true)) then
11331-
"if (_clockStart[clockIndex - 1]) return;"
11326+
case SIMVAR(varKind = CLOCKED_STATE(isStartFixed = isStartFixed)) then
11327+
'if (<%if isStartFixed then "_clockStart[clockIndex - 1] || "%>_clockSubactive[clockIndex - 1]) return;'
1133211328
let expPart = daeExp(exp, context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
1133311329

1133411330
match cref
@@ -12557,13 +12553,12 @@ end createEvaluateAll;
1255712553
template createTimeConditionTreatments(String numberOfTimeEvents)
1255812554
::=
1255912555
<<
12560-
1256112556
// treatment of clocks in model as time events
1256212557
for (int i = <%numberOfTimeEvents%>; i < _dimTimeEvent; i++) {
1256312558
if (_time_conditions[i]) {
1256412559
evaluateClocked(i - <%numberOfTimeEvents%> + 1);
1256512560
_time_conditions[i] = false; // reset clock after one evaluation
12566-
12561+
_clockSubactive[i - <%numberOfTimeEvents%>] = false;
1256712562
}
1256812563
}
1256912564
>>

SimulationRuntime/cpp/Core/System/SystemDefaultImplementation.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ SystemDefaultImplementation::SystemDefaultImplementation(IGlobalSettings *global
5858
, _clockTime (NULL)
5959
, _clockCondition (NULL)
6060
, _clockStart (NULL)
61+
, _clockSubactive (NULL)
6162
, _outputStream(NULL)
6263
, _callType (IContinuous::UNDEF_UPDATE)
6364
, _initial (false)
@@ -96,6 +97,7 @@ SystemDefaultImplementation::SystemDefaultImplementation(SystemDefaultImplementa
9697
, _clockTime (NULL)
9798
, _clockCondition (NULL)
9899
, _clockStart (NULL)
100+
, _clockSubactive (NULL)
99101
, _outputStream(NULL)
100102
, _callType (IContinuous::UNDEF_UPDATE)
101103
, _initial (false)
@@ -140,6 +142,7 @@ SystemDefaultImplementation::~SystemDefaultImplementation()
140142
if(_clockTime) delete [] _clockTime;
141143
if(_clockCondition) delete [] _clockCondition;
142144
if(_clockStart) delete [] _clockStart;
145+
if(_clockSubactive) delete [] _clockSubactive;
143146
if(__daeResidual) delete [] __daeResidual;
144147
}
145148

@@ -254,11 +257,13 @@ void SystemDefaultImplementation::initialize()
254257
memset(_clockCondition,false,(_dimClock)*sizeof(bool));
255258
if (_clockStart) delete [] _clockStart;
256259
_clockStart = new bool [_dimClock];
260+
if (_clockSubactive) delete [] _clockSubactive;
261+
_clockSubactive = new bool [_dimClock];
257262
}
258263
if(_dimRHS>0)
259264
{
260-
if (__daeResidual) delete [] __daeResidual;
261-
__daeResidual = new double [_dimRHS];
265+
if (__daeResidual) delete [] __daeResidual;
266+
__daeResidual = new double [_dimRHS];
262267
}
263268
_start_time = 0.0;
264269
_terminal = false;
@@ -428,10 +433,11 @@ void SystemDefaultImplementation::setReal(const double* z)
428433
}
429434
};
430435

431-
void SystemDefaultImplementation::setClock(const bool* z)
436+
void SystemDefaultImplementation::setClock(const bool* tick, const bool* subactive)
432437
{
433-
for(int i = _dimTimeEvent - _dimClock; i < _dimTimeEvent; i++) {
434-
_time_conditions[i] = z[i];
438+
for (int i = 0; i < _dimClock; i++) {
439+
_time_conditions[_dimTimeEvent - _dimClock + i] = tick[i];
440+
_clockSubactive[i] = subactive[i];
435441
}
436442
}
437443

SimulationRuntime/cpp/Include/Core/System/SystemDefaultImplementation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class BOOST_EXTENSION_SYSTEM_DECL SystemDefaultImplementation
113113
virtual void setString(const std::string* z);
114114

115115
/// Provide clocks
116-
virtual void setClock(const bool* z);
116+
virtual void setClock(const bool* tick, const bool* subactive);
117117

118118
/// Provide the right hand side
119119
virtual void setStateDerivatives(const double* f);
@@ -183,6 +183,7 @@ class BOOST_EXTENSION_SYSTEM_DECL SystemDefaultImplementation
183183
double *_clockTime; ///< time of clock ticks
184184
bool *_clockCondition; ///< clock tick active
185185
bool *_clockStart; ///< only active at clock start
186+
bool *_clockSubactive; ///< don't update states
186187
std::ostream *_outputStream; ///< Output stream for results
187188

188189
IContinuous::UPDATETYPE _callType;

SimulationRuntime/cpp/Include/FMU2/FMU2Interface.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,12 @@ extern "C"
228228

229229
fmi2Status fmi2GetClock(fmi2Component c,
230230
const fmi2Integer clockIndex[],
231-
size_t nClockIndex, fmi2Boolean active[])
231+
size_t nClockIndex, fmi2Boolean tick[])
232232
{
233233
FMU2Wrapper *w = reinterpret_cast<FMU2Wrapper*>(c);
234234
LOG_CALL(w, "fmi2GetClock(nClockIndex = %d)", nClockIndex);
235235
try {
236-
return w->getClock(clockIndex, nClockIndex, active);
236+
return w->getClock(clockIndex, nClockIndex, tick);
237237
}
238238
CATCH_EXCEPTION(w);
239239
}
@@ -300,12 +300,13 @@ extern "C"
300300

301301
fmi2Status fmi2SetClock(fmi2Component c,
302302
const fmi2Integer clockIndex[],
303-
size_t nClockIndex, const fmi2Boolean active[])
303+
size_t nClockIndex, const fmi2Boolean tick[],
304+
const fmi2Boolean subactive[])
304305
{
305306
FMU2Wrapper *w = reinterpret_cast<FMU2Wrapper*>(c);
306307
LOG_CALL(w, "fmi2SetClock(nClockIndex = %d)", nClockIndex);
307308
try {
308-
return w->setClock(clockIndex, nClockIndex, active);
309+
return w->setClock(clockIndex, nClockIndex, tick, subactive);
309310
}
310311
CATCH_EXCEPTION(w);
311312
}

SimulationRuntime/cpp/Include/FMU2/FMU2Wrapper.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,17 @@ FMU2Wrapper::FMU2Wrapper(fmi2String instanceName, fmi2String GUID,
125125
_model->initializeMemory();
126126
_model->initializeFreeVariables();
127127
_string_buffer.resize(_model->getDimString());
128-
_clock_buffer = new bool[_model->getDimClock()];
129-
std::fill(_clock_buffer, _clock_buffer + _model->getDimClock(), false);
130-
_nclock_active = 0;
128+
_clockTick = new bool[_model->getDimClock()];
129+
_clockSubactive = new bool[_model->getDimClock()];
130+
std::fill(_clockTick, _clockTick + _model->getDimClock(), false);
131+
std::fill(_clockSubactive, _clockSubactive + _model->getDimClock(), false);
132+
_nclockTick = 0;
131133
}
132134

133135
FMU2Wrapper::~FMU2Wrapper()
134136
{
135-
delete [] _clock_buffer;
137+
delete [] _clockSubactive;
138+
delete [] _clockTick;
136139
delete _model;
137140
}
138141

@@ -234,9 +237,10 @@ void FMU2Wrapper::updateModel()
234237

235238
fmi2Status FMU2Wrapper::setTime(fmi2Real time)
236239
{
237-
if (_nclock_active > 0) {
238-
std::fill(_clock_buffer, _clock_buffer + _model->getDimClock(), false);
239-
_nclock_active = 0;
240+
if (_nclockTick > 0) {
241+
std::fill(_clockTick, _clockTick + _model->getDimClock(), false);
242+
std::fill(_clockSubactive, _clockSubactive + _model->getDimClock(), false);
243+
_nclockTick = 0;
240244
}
241245
_model->setTime(time);
242246
_need_update = true;
@@ -316,11 +320,17 @@ fmi2Status FMU2Wrapper::setString(const fmi2ValueReference vr[], size_t nvr,
316320
}
317321

318322
fmi2Status FMU2Wrapper::setClock(const fmi2Integer clockIndex[],
319-
size_t nClockIndex, const fmi2Boolean active[])
323+
size_t nClockIndex, const fmi2Boolean tick[],
324+
const fmi2Boolean subactive[])
320325
{
321326
for (int i = 0; i < nClockIndex; i++) {
322-
_clock_buffer[clockIndex[i] - 1] = active[i];
323-
_nclock_active ++;
327+
_clockTick[clockIndex[i] - 1] = tick[i];
328+
if (subactive != NULL)
329+
_clockSubactive[clockIndex[i] - 1] = subactive[i];
330+
}
331+
_nclockTick = 0;
332+
for (int i = 0; i < _model->getDimClock(); i++) {
333+
_nclockTick += _clockTick[i]? 1: 0;
324334
}
325335
_need_update = true;
326336
return fmi2OK;
@@ -395,10 +405,10 @@ fmi2Status FMU2Wrapper::getString(const fmi2ValueReference vr[], size_t nvr,
395405
}
396406

397407
fmi2Status FMU2Wrapper::getClock(const fmi2Integer clockIndex[],
398-
size_t nClockIndex, fmi2Boolean active[])
408+
size_t nClockIndex, fmi2Boolean tick[])
399409
{
400410
for (int i = 0; i < nClockIndex; i++) {
401-
active[i] = _clock_buffer[clockIndex[i] - 1];
411+
tick[i] = _clockTick[clockIndex[i] - 1];
402412
}
403413
return fmi2OK;
404414
}
@@ -416,13 +426,14 @@ fmi2Status FMU2Wrapper::getInterval(const fmi2Integer clockIndex[],
416426
fmi2Status FMU2Wrapper::newDiscreteStates(fmi2EventInfo *eventInfo)
417427
{
418428
if (_need_update) {
419-
if (_nclock_active > 0)
420-
_model->setClock(_clock_buffer);
429+
if (_nclockTick > 0)
430+
_model->setClock(_clockTick, _clockSubactive);
421431
updateModel();
422-
if (_nclock_active > 0) {
432+
if (_nclockTick > 0) {
423433
// reset clocks
424-
std::fill(_clock_buffer, _clock_buffer + _model->getDimClock(), false);
425-
_nclock_active = 0;
434+
std::fill(_clockTick, _clockTick + _model->getDimClock(), false);
435+
std::fill(_clockSubactive, _clockSubactive + _model->getDimClock(), false);
436+
_nclockTick = 0;
426437
}
427438
}
428439
// Check if an Zero Crossings happend

SimulationRuntime/cpp/Include/FMU2/FMU2Wrapper.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class FMU2Wrapper
128128
virtual fmi2Status getString (const fmi2ValueReference vr[], size_t nvr,
129129
fmi2String value[]);
130130
virtual fmi2Status getClock (const fmi2Integer clockIndex[],
131-
size_t nClockIndex, fmi2Boolean active[]);
131+
size_t nClockIndex, fmi2Boolean tick[]);
132132
virtual fmi2Status getInterval(const fmi2Integer clockIndex[],
133133
size_t nClockIndex, fmi2Real interval[]);
134134

@@ -141,7 +141,8 @@ class FMU2Wrapper
141141
virtual fmi2Status setString (const fmi2ValueReference vr[], size_t nvr,
142142
const fmi2String value[]);
143143
virtual fmi2Status setClock (const fmi2Integer clockIndex[],
144-
size_t nClockIndex, const fmi2Boolean active[]);
144+
size_t nClockIndex, const fmi2Boolean tick[],
145+
const fmi2Boolean subactive[]);
145146
virtual fmi2Status setInterval(const fmi2Integer clockIndex[],
146147
size_t nClockIndex, const fmi2Real interval[]);
147148

@@ -166,8 +167,9 @@ class FMU2Wrapper
166167
Logger *_logger;
167168
MODEL_CLASS *_model;
168169
std::vector<string> _string_buffer;
169-
bool *_clock_buffer;
170-
int _nclock_active;
170+
bool *_clockTick;
171+
bool *_clockSubactive;
172+
int _nclockTick;
171173
double _need_update;
172174
void updateModel();
173175

0 commit comments

Comments
 (0)