Skip to content

Commit

Permalink
Cleanup delay code (#11934)
Browse files Browse the repository at this point in the history
  • Loading branch information
phannebohm committed Feb 2, 2024
1 parent e8d1048 commit 45ebb20
Show file tree
Hide file tree
Showing 22 changed files with 140 additions and 113 deletions.
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/BackEnd/FindZeroCrossings.mo
Expand Up @@ -1008,7 +1008,7 @@ algorithm
(delay, ((_, relations, samples, numMathFunctions), tp1)) := Expression.traverseExpTopDown(delay, collectZC, ((ZeroCrossings.new(), relations, samples, numMathFunctions), tp1));

// create zero crossing function
eres1 := DAE.CALL(Absyn.IDENT("delayZeroCrossing"), {index, DAE.ICONST(DoubleEnded.length(relations)), e, delay, delayMax}, attr);
eres1 := DAE.CALL(Absyn.IDENT("delayZeroCrossing"), {index, DAE.ICONST(DoubleEnded.length(relations)), delay}, attr);
e_1 := DAE.RELATION(eres1, DAE.GREATER(DAE.T_REAL_DEFAULT) ,DAE.RCONST(0.0), DoubleEnded.length(relations), NONE());
zc := createZeroCrossing(eres1, {eq_count});
(eres, relations) := zcIndexRelation(e_1, relations, DoubleEnded.length(relations), zc);
Expand Down
8 changes: 3 additions & 5 deletions OMCompiler/Compiler/Template/CodegenCFunctions.tpl
Expand Up @@ -6713,7 +6713,7 @@ let &sub = buffer ""
let var1 = daeExp(e, context, &preExp, &varDecls, &auxFunction)
let var2 = daeExp(d, context, &preExp, &varDecls, &auxFunction)
let var3 = daeExp(delayMax, context, &preExp, &varDecls, &auxFunction)
let &preExp += '<%tvar%> = delayImpl(data, threadData, <%index%>, <%var1%>, data->localData[0]->timeValue, <%var2%>, <%var3%>);<%\n%>'
let &preExp += '<%tvar%> = delayImpl(data, threadData, <%index%>, <%var1%>, <%var2%>, <%var3%>);<%\n%>'
tvar

case CALL(path=IDENT(name="spatialDistribution"), expLst={ICONST(integer=index), in0, in1, posX, posVelo}) then
Expand Down Expand Up @@ -6755,11 +6755,9 @@ let &sub = buffer ""
'data->simulationInfo->samples[<%intSub(index, 1)%>]'
end match

case CALL(path=IDENT(name="delayZeroCrossing"), expLst={ICONST(integer=index), ICONST(integer=rindex), e, delay, delayMax}) then
let e_T = daeExp(e, context, &preExp, &varDecls, &auxFunction)
case CALL(path=IDENT(name="delayZeroCrossing"), expLst={ICONST(integer=index), ICONST(integer=rindex), delay}) then
let delay_T = daeExp(delay, context, &preExp, &varDecls, &auxFunction)
let delayMax_T = daeExp(delayMax, context, &preExp, &varDecls, &auxFunction)
'delayZeroCrossing(data, threadData, <%index%>, <%rindex%>, <%e_T%>, <%delay_T%>, <%delayMax_T%>)'
'delayZeroCrossing(data, threadData, <%index%>, <%rindex%>, <%delay_T%>)'

case CALL(path=IDENT(name="spatialDistributionZeroCrossing"), expLst={ICONST(integer=index), ICONST(integer=rindex), xPos, dir}) then
let xPos_T = daeExp(xPos, context, &preExp, &varDecls, &auxFunction)
Expand Down
105 changes: 43 additions & 62 deletions OMCompiler/SimulationRuntime/c/simulation/solver/delay.c
Expand Up @@ -47,9 +47,7 @@ void printDelayBuffer(void* data, int stream, void* elemPointer);


/**
* @brief Find row with greatest time that is greater than or equal to 'time'
*
* So all buffer elements before returned row index need to be removed from buffer.
* @brief Find row with greatest time that is smaller than or equal to 'time'.
*
* @param[in] time Time value to search for.
* @param[in] delayStruct Ringbuffer with stored delay values.
Expand All @@ -72,12 +70,12 @@ static int findTime(double time, RINGBUFFER *delayStruct, int* foundEvent)
curTime = bufferElem->t;

/* If searched time is smaller then first element return first position */
if(time < curTime) {
if (time < curTime) {
return pos;
}

/* Search for time starting at begin of ring buffer */
while(pos < end-1) {
while (pos < end-1) {
pos++;
bufferElem = getRingData(delayStruct, pos);
prevTime = curTime;
Expand Down Expand Up @@ -111,9 +109,10 @@ static int findTime(double time, RINGBUFFER *delayStruct, int* foundEvent)
*/
void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double delayTime, double delayMax)
{
RINGBUFFER* delayStruct = data->simulationInfo->delayStructure[exprNumber];
int row;
int foundEvent;
int length = ringBufferLength(data->simulationInfo->delayStructure[exprNumber]);
int length = ringBufferLength(delayStruct);
double time = data->localData[0]->timeValue;
TIME_AND_VALUE tpl;
TIME_AND_VALUE* lastElem;
Expand All @@ -122,13 +121,14 @@ void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber
assertStreamPrint(threadData, 0 <= exprNumber, "storeDelayedExpression: invalid expression number %d", exprNumber);

/* Check if time is greater equal then last stored time in delay structure */
/* ph: Is this needed because of event search? */
if (length > 0) {
lastElem = getRingData(data->simulationInfo->delayStructure[exprNumber], length-1);
lastElem = getRingData(delayStruct, length-1);
while (time < lastElem->t && length > 0) {
removeLastRingData(data->simulationInfo->delayStructure[exprNumber],1);
length = ringBufferLength(data->simulationInfo->delayStructure[exprNumber]);
removeLastRingData(delayStruct,1);
length = ringBufferLength(delayStruct);
if (length > 0) {
lastElem = getRingData(data->simulationInfo->delayStructure[exprNumber], length-1);
lastElem = getRingData(delayStruct, length-1);
}
}
}
Expand All @@ -137,10 +137,10 @@ void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber
* This should happen after an event was found and the event iteration finished */
if (length > 0) {
if (fabs(lastElem->t-time) < 1e-10 && fabs(lastElem->value-exprValue) < 1e-10) {
/* Remove stuff that is not needed any more */
row = findTime(time-delayTime+1e-10, data->simulationInfo->delayStructure[exprNumber], &foundEvent);
if(row > 0){
dequeueNFirstRingDatas(data->simulationInfo->delayStructure[exprNumber], row);
/* Dequeue no longer needed values from ring buffer */
row = findTime(time-delayTime+1e-10, delayStruct, &foundEvent);
if (row > 0) {
dequeueNFirstRingDatas(delayStruct, row);
}
return;
}
Expand All @@ -149,17 +149,17 @@ void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber
/* Append expression value to delay ring buffer */
tpl.t = time;
tpl.value = exprValue;
appendRingData(data->simulationInfo->delayStructure[exprNumber], &tpl);
appendRingData(delayStruct, &tpl);

/* Dequeue not longer needed values from ring buffer */
row = findTime(time-delayTime+DBL_EPSILON, data->simulationInfo->delayStructure[exprNumber], &foundEvent);
if(row > 0 && !foundEvent){
dequeueNFirstRingDatas(data->simulationInfo->delayStructure[exprNumber], row);
/* Dequeue no longer needed values from ring buffer */
row = findTime(time-delayTime+DBL_EPSILON, delayStruct, &foundEvent);
if (row > 0 && !foundEvent) {
dequeueNFirstRingDatas(delayStruct, row);
}

/* Debug print */
infoStreamPrint(LOG_DELAY, 0, "storeDelayed[%d] (%g,%g) position=%d", exprNumber, time, exprValue, ringBufferLength(data->simulationInfo->delayStructure[exprNumber]));
printRingBuffer(data->simulationInfo->delayStructure[exprNumber], LOG_DELAY, printDelayBuffer);
infoStreamPrint(LOG_DELAY, 0, "storeDelayed[%d] (%g,%g) position=%d", exprNumber, time, exprValue, ringBufferLength(delayStruct));
printRingBuffer(delayStruct, LOG_DELAY, printDelayBuffer);
}


Expand All @@ -170,12 +170,11 @@ void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber
* @param threadData Pointer to thread data.
* @param exprNumber Index of delay expression.
* @param exprValue Value of delay expression.
* @param time Current simulation time.
* @param delayTime Amount of time exprValue should be delayed.
* @param delayMax Maximum time to delay exprValue.
* @return double Return delayed value.
*/
double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double time, double delayTime, double delayMax)
double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double delayTime, double delayMax)
{
RINGBUFFER* delayStruct = data->simulationInfo->delayStructure[exprNumber];
double timeStamp;
Expand All @@ -187,6 +186,7 @@ double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double ex
int i;
int foundEvent;
int length = ringBufferLength(delayStruct);
double time = data->localData[0]->timeValue;

infoStreamPrint(LOG_DELAY, 0, "delayImpl: exprNumber = %d, exprValue = %g, time = %g, delayTime = %g", exprNumber, exprValue, time, delayTime);

Expand All @@ -199,65 +199,55 @@ double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double ex
assertStreamPrint(threadData, delayTime <= delayMax, "Too large delay requested: delayTime = %g, delayMax = %g", delayTime, delayMax);

/* Return expression value before simulation start */
if(time <= data->simulationInfo->startTime)
{
return (exprValue);
if (time <= data->simulationInfo->startTime) {
return exprValue;
}

/* Empty delay buffer at initialization phase */
if(length == 0)
{
if (length == 0) {
infoStreamPrint(LOG_EVENTS, 0, "delayImpl: Missing initial value, using argument value %g instead.", exprValue);
return (exprValue);
return exprValue;
}

/* Return oldest element in ring buffer */
if(time <= data->simulationInfo->startTime + delayTime)
{
if (time <= data->simulationInfo->startTime + delayTime) {
return ((TIME_AND_VALUE*)getRingData(delayStruct, 0))->value;
}
/* return expr(time-delayTime) */
else
{
else {
timeStamp = time - delayTime;

/* find the row for the lower limit */
if(timeStamp > ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->t)
{
if (timeStamp > ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->t) {
/* delay between the last accepted time step and the current time */
time0 = ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->t;
value0 = ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->value;
time1 = time;
value1 = exprValue;
}
else
{
} else {
i = findTime(timeStamp, delayStruct, &foundEvent);
assertStreamPrint(threadData, i < length, "%d = i < length = %d", i, length);
time0 = ((TIME_AND_VALUE*)getRingData(delayStruct, i))->t;
value0 = ((TIME_AND_VALUE*)getRingData(delayStruct, i))->value;

/* was it the last value? */
if(i+1 == length)
{
if (i+1 == length) {
return value0;
}
time1 = ((TIME_AND_VALUE*)getRingData(delayStruct, i+1))->t;
value1 = ((TIME_AND_VALUE*)getRingData(delayStruct, i+1))->value;
}
/* Return left value */
if(time0 == timeStamp)
{
if (time0 == timeStamp) {
return value0;
}
/* Return right value */
else if(time1 == timeStamp)
{
else if (time1 == timeStamp) {
return value1;
}
/* linear interpolation */
else
{
/* FIXME instead of linear, do the same interpolation order as the integrator */
else {
timedif = time1 - time0;
dt0 = time1 - timeStamp;
dt1 = timeStamp - time0;
Expand All @@ -275,37 +265,28 @@ double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double ex
* @param threadData Used for error handling.
* @param exprNumber Index of delay.
* @param relationIndex Index of relation used for zero crossing.
* @param delayValue Value to store in delay ringbuffer.
* @param delayTime Time to delay expValue.
* @param delayMax Maximum allowed delay time, defaults to delayTime.
* @return double Value of zeroCrossing at current simulation time.
*/
double delayZeroCrossing(DATA* data, threadData_t *threadData, unsigned int exprNumber, unsigned int relationIndex, double delayValue, double delayTime, double delayMax)
double delayZeroCrossing(DATA* data, threadData_t *threadData, unsigned int exprNumber, unsigned int relationIndex, double delayTime)
{
RINGBUFFER* delayStruct = data->simulationInfo->delayStructure[exprNumber];
int foundEvent;
int eventPos;
double zeroCrossingValue;
double zeroCrossingValue = data->simulationInfo->zeroCrossingsPre[relationIndex];
double time = data->localData[0]->timeValue;

RINGBUFFER* delayStruct = data->simulationInfo->delayStructure[exprNumber];
zeroCrossingValue = data->simulationInfo->zeroCrossingsPre[relationIndex];

if (ringBufferLength(delayStruct) == 0)
{
if (ringBufferLength(delayStruct) == 0) {
return zeroCrossingValue;
}

/* Find first event on ring buffer */
findTime(time - delayTime, delayStruct, &foundEvent);

/* Flip sign of ZC if an event was found */
if (!foundEvent)
{
return zeroCrossingValue;
}
else
{
if (foundEvent) {
return -zeroCrossingValue;
} else {
return zeroCrossingValue;
}
}

Expand Down
17 changes: 5 additions & 12 deletions OMCompiler/SimulationRuntime/c/simulation/solver/delay.h
Expand Up @@ -42,23 +42,16 @@ typedef struct TIME_AND_VALUE
double value;
} TIME_AND_VALUE;

typedef struct EXPRESSION_DELAY_BUFFER
{
long currentIndex;
long maxExpressionBuffer;
TIME_AND_VALUE *expressionDelayBuffer;
}EXPRESSION_DELAY_BUFFER;

#ifdef __cplusplus
extern "C" {
extern "C" {
#endif

double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double t, double delayTime, double maxDelay);
void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double delayTime, double delayMax);
double delayZeroCrossing(DATA* data, threadData_t *threadData, unsigned int exprNumber, unsigned int relationIndex, double delayValue, double delayTime, double delayMax);
double delayImpl(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double delayTime, double delayMax);
void storeDelayedExpression(DATA* data, threadData_t *threadData, int exprNumber, double exprValue, double delayTime, double delayMax);
double delayZeroCrossing(DATA* data, threadData_t *threadData, unsigned int exprNumber, unsigned int relationIndex, double delayTime);

#ifdef __cplusplus
}
}
#endif

#endif
Expand Up @@ -1218,6 +1218,7 @@ void initializeDataStruc(DATA *data, threadData_t *threadData)
for(i=0; i<data->modelData->nDelayExpressions; i++)
{
// TODO: Calculate how big ringbuffer should be for each delay expression
// can be estimated by lower bound delayMax/stepSize
data->simulationInfo->delayStructure[i] = allocRingBuffer(1024, sizeof(TIME_AND_VALUE));
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/SimulationRuntime/c/simulation_data.h
Expand Up @@ -697,7 +697,7 @@ typedef struct SIMULATION_INFO
modelica_real stopTime; /* Stop time of the simulation */
int useStopTime;
modelica_integer numSteps;
modelica_real stepSize;
modelica_real stepSize; /* FIXME what is this? The integrator's current step size */
modelica_real minStepSize; /* defines the minimal step size */
modelica_real tolerance;
const char *solverMethod;
Expand Down
20 changes: 15 additions & 5 deletions testsuite/Makefile
Expand Up @@ -56,7 +56,12 @@ simulationasserts.log \
simulationbuilt-in-functions.log \
simulationconnectors.log \
simulationdaemode.log \
simulationnewbackend.log \
simulationnewbackend-arrayhandling.log \
simulationnewbackend-basics.log \
simulationnewbackend-event_handling.log \
simulationnewbackend-functions.log \
simulationnewbackend-records.log \
simulationnewbackend-ScalableTestsuite.log \
simulationdeclarations.log \
simulationenums.log \
simulationequations.log \
Expand All @@ -77,7 +82,8 @@ simulationothers.log \
simulationpackages.log \
simulationrecords.log \
simulationsolver.log \
simulationspartialDistribution.log \
simulationBuiltin_delay.log \
simulationBuiltin_spatialDistribution.log \
simulationtypes.log \
simulationmodelicamsl22.log \
msl31mediasimulation.log \
Expand Down Expand Up @@ -129,7 +135,7 @@ simulationothers.log \
simulationpackages.log \
simulationrecords.log \
simulationsolver.log \
simulationspartialDistribution.log \
simulationBuiltin_spatialDistribution.log \
simulationtypes.log \
modelicaasserts.log \
modelicaalgorithms-functions.log \
Expand Down Expand Up @@ -338,6 +344,7 @@ simulationnewbackend-functions.log: omc-diff
@echo $@ done
simulationnewbackend-records.log: omc-diff
$(MAKE) -C simulation/modelica/NBackend/records/ -f Makefile test > $@
@echo $@ done
simulationnewbackend-ScalableTestsuite.log: omc-diff
$(MAKE) -C simulation/modelica/NBackend/ScalableTestsuite/ -f Makefile test > $@
@echo $@ done
Expand Down Expand Up @@ -404,8 +411,11 @@ simulationrecords.log: omc-diff
simulationsolver.log: omc-diff
$(MAKE) -C simulation/modelica/solver -f Makefile test > $@
@echo $@ done
simulationspartialDistribution.log: omc-diff
$(MAKE) -C simulation/modelica/spatialDistribution -f Makefile test > $@
simulationBuiltin_delay.log: omc-diff
$(MAKE) -C simulation/modelica/built_in_functions/delay -f Makefile test > $@
@echo $@ done
simulationBuiltin_spatialDistribution.log: omc-diff
$(MAKE) -C simulation/modelica/built_in_functions/spatialDistribution -f Makefile test > $@
@echo $@ done
simulationtypes.log: omc-diff
$(MAKE) -C simulation/modelica/types -f Makefile test > $@
Expand Down
1 change: 0 additions & 1 deletion testsuite/simulation/modelica/built_in_functions/Makefile
Expand Up @@ -3,7 +3,6 @@ TEST = ../../../rtest -v
TESTFILES = \
BuiltinMath.mos \
Compare.mos \
Delay.mos \
Delta.mos \
DerInvalid.mos \
DerValid.mos \
Expand Down

0 comments on commit 45ebb20

Please sign in to comment.