-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement DELAY FIXED function #108
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ToddFincannon Only spotted one potential issue that I noted in a comment. The rest looks great to me. Once you resolve that issue, this will be ready to merge.
The suggested change worked after an additional fix. Because DELAY FIXED makes a level variable, when we check to see whether we have reached the delay time yet, we have to compare TIME to the following time step. This was true before, but the issue was masked by the fact that the initial value and early buffer values were both zero. I added a new test model called |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new fixes and tests look good. I'll merge this shortly.
Fixes #29
DELAY FIXED
requires something none of the other Vensim functions implemented so far need: auxiliary storage of past variable values. The number of values to be stored depends on the delay time, which is quantized to a multiple of TIME STEP. The storage buffer must be allocated at runtime, because the delay time is not known until then. To support this, a newFixedDelay
structure is added that implements a ring buffer sized to the number of delay steps.I followed the Vensim docs which mention that
DELAY FIXED
is a level var with a special fixed delay subtype. It behaves very much like a level, with a separate initial value set in the init phase, and with evaluation at the same time as other levels. The subtype indicates the special handling that is required, starting with theFixedDelay
support structure mentioned above. Code is generated to allocate and initialize this structure at init time just after setting the initial value for theDELAY FIXED
variable. Note that theFixedDelay
structure is not a Vensim variable. It is generated as a special case.The other special handling that is needed is: rewriting the
DELAY FIXED
equation at eval time to remove the initialization arguments (similar to INTEG) and add theFixedDelay
support argument; and declaring theFixedDelay
pointer at decl time.When the
DELAY FIXED
variable is subscripted, theFixedDelay
struct is also subscripted. It uses the LHS subscripts. Other variables occurring in arguments on the RHS are still free to use different subscripts.A new
_DELAY_FIXED
Vensim function in C rounds out the implementation. It is coupled with__new_fixed_delay
to allocate and initialize theFixedDelay
structure._DELAY_FIXED
implements a straightforward ring buffer with one twist: when pulling a delayed value from the buffer, it increments the current position first. This is becauseDELAY FIXED
is a level with a value evaluated for the next time step.