Skip to content
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

Clarify rules on fmi3GetInterval*/fmi3GetShift* functions with regards to periodic input clocks #2018

Open
pmai opened this issue Dec 4, 2024 · 2 comments
Assignees

Comments

@pmai
Copy link
Collaborator

pmai commented Dec 4, 2024

The standard seems to suggest that these functions can be called for clocks with constant/fixed/tunable intervalVariability - at least under some circumstances - in Table 5 by listing as related API:

  • constant:

    fmi3SetClock in EventMode, fmi3ActivateModelPartition in ClockActivationMode, fmi3GetInterval and fmi3GetShift in InitializationMode

However for fixed/tunable it lists:

  • fixed:

    fmi3SetClock in EventMode, fmi3ActivateModelPartition in ClockActivationMode,

    • if intervalDecimal is defined, fmi3SetInterval in InitializationMode,
    • if intervalDecimal is not defined, fmi3GetInterval and fmi3GetShift in InitializationMode

So interestingly, for fixed/tunable you can only call fmi3GetInterval/fmi3GetShift if no interval is provided in the modelDescription.xml.

While Table 6 then just generally states on T_interval_i:

The time interval until the next Clock tick, defined differently for the different Clock types. Tinterval,i
can be set with fmi3SetIntervalDecimal or retrieved with fmi3GetIntervalDecimal as floating point value, or as rational number using fmi3SetIntervalFraction or fmi3GetIntervalFraction.

which might or might not suggest that fmi3GetInterval* can always be called.

Furthermore the definition of fmi3GetInterval* then provides wording that does not suggest anyone thought of the semantics of calling them for periodic clocks:

  • qualifiers is an array of size nValueReferences to retrieve the Clocks qualifiers.
    qualifiers describes how to treat the intervals and counters arguments and is defined as:

...

with the following meanings:

  • fmi3IntervalChanged is returned to indicate that the value for the interval has changed for this Clock.
    Any previously returned intervals (if any) are overwritten with the current value.
    The new Clock interval is relative to the time of the current EventMode or ClockUpdateMode in contrast to the interval of a periodic Clock, where the interval is defined as the time between consecutive Clock ticks.
    In Scheduled Execution this means that the corresponding model partition must be scheduled or re-scheduled (if a previous call to fmi3GetInterval returned fmi3IntervalChanged).
  • fmi3IntervalUnchanged is returned if a previous call to fmi3GetInterval already returned a value qualified with fmi3IntervalChanged which has not changed since.
    In Scheduled Execution this means the corresponding model partition has already been scheduled.
  • fmi3IntervalNotYetKnown is returned for a countdown-aperiodic-clock,countdown Clock for which the next interval is not yet known.
    This qualifier value can only be returned directly after the Clock was active and previous calls to fmi3GetInterval never returned fmi3IntervalChanged (nor fmi3IntervalUnchanged).
    In Scheduled Execution this return value means that the corresponding model partition cannot be scheduled yet.

None of the options provided seem to take constant (or even just periodic) clocks into account, and hence it is unclear what should be returned:

  • fmi3IntervalChanged seems to assume we are in Event Mode, but the calls allowed are in Initialization Mode, which is not Event Mode, and it also suggests the intervals are relative to some current time, which again they should not be for periodic clocks.
  • fmi3IntervalUnchanged is only allowed if fmi3IntervalChanged has been reported once, so no go for periodic/constant clocks.
  • fmi3IntervalNotYetKnown is only available for countdown clocks when the next interval is not yet known.

Taken together I think the description of this in the standard should be refined to precisely state whether and when it is allowed to call fmi3GetInterval* and what should be returned for periodic clocks.

@PTaeuberDS
Copy link
Contributor

I think whether and when it is allowed to call fmi3GetInterval* is already precisely defined.

So interestingly, for fixed/tunable you can only call fmi3GetInterval/fmi3GetShift if no interval is provided in the modelDescription.xml.

If no interval is provided the standard defines that the interval depends on fixed/tunable parameters. In this case the importer must be able to get the interval.
If an interval is defined, the importer sets the interval directly with fmi3SetInterval*.

While Table 6 then just generally states on T_interval_i:

The time interval until the next Clock tick, defined differently for the different Clock types. Tinterval,i
can be set with fmi3SetIntervalDecimal or retrieved with fmi3GetIntervalDecimal as floating point value, or as rational number using fmi3SetIntervalFraction or fmi3GetIntervalFraction.

which might or might not suggest that fmi3GetInterval* can always be called.

"can be set with fmi3SetIntervalDecimal OR retrieved with fmi3GetIntervalDecimal" is true for all time-based Clock types. Which call is allowed for a specific Clock, depends on the Clock type. Maybe an "either ... or" should be used here.

fmi3IntervalChanged seems to assume we are in Event Mode, but the calls allowed are in Initialization Mode, which is not Event Mode,

Yes. Adding InitializationMode in the sentence would fix that part, right?

and it also suggests the intervals are relative to some current time, which again they should not be for periodic clocks.

Yes, this contradicts the definition of T_interval_i for periodic Clocks. But otherwise it could happen that the next Clock tick is already in the past. E.g., if the interval was 1s and is changed at t=0.75s to 0.5s. The the last Clock tick was at t=0 and the next at t=0.5, which is in the past.

fmi3IntervalUnchanged is only allowed if fmi3IntervalChanged has been reported once, so no go for periodic/constant clocks.

The first call to fmi3GetInterval* at InitializationMode would return fmi3IntervalChanged. Following calls return fmi3IntervalUnchanged, until, e.g., a tunable Clock depending on parameters changes its interval.

So, I think, the only issue here is the definition of the interval that is returned by fmi3GetInterval*.

One solution would be to change the definition of T_interval_i for periodic Clocks to something like this:

"When the interval is unchanged (no new interval is retrieved by fmi3GetInterval*), the time interval from the previous Clock tick to the current Clock tick, specified differently for the different Clock types. If a new interval is retrieved, the first new Clock interval is relative to the time of the current EventMode or ClockUpdateMode."

@chrbertsch
Copy link
Collaborator

Pierre: the questions is, when you are allowed to call "fmi3GetInterval". This is not clearly defined, and the result values are not clearly defined.
Patrick: I think it is defined, when to call them
Pierre: I do not agree. One can read it in different ways. We read it that for constant periodic clocks one would not call it.
Patrick: For this case it is defined in the table 5.
Pierre: for fixed and tunable clocks it is suggested that one can only call "setInterval". There is no clear statement "you can always call "fmi3GetInterval" for each clock and what the return value should be. And the return values are not defined.
Masoud: You have a loss of precision with floating point numbers, e.g. 1/3
Pierre: for 1/3 you need the fraction representation. For floating points it is a solved problem.
Pierre: For constant clocks it is said that you can call fmi3GetInterval, but not for fixed ....
I do not see the reason why it is forbidden
Patrick: the problem is that we mixed it up ...
Pierre: We have to decide whether one can call fmi3getInterval, if one can get it in some other way.
Patrick: Suggestion: One can call "fmi3getInterval" always , define when to set fmi3setInterval
Pierre: this would make things easier for importers (but could be done differently)
Pierre: We have to specify the return values.
Patrick: the first call should return ... later calls ...
Pierre: the problem with this is that ... is that it refers to the current point of time ... .
For tunable parameters this is fine
Patrick: I made a proposal in the comment above.
Pierre: how is "unchanged" defined? ...
Patrick: two cases: when you set the new intervall, you cannot get it; when the FMU changes it, it sets "eventModeNeeded"
Pierre: so you are not allowed to call getIntervall always
Masoud: I want to make an anlogy with normal variables ... why not allow calling it?
Klaus: E.g. calling getReal for inputs. But here this is relative to the time point when you call this
Pierre: we have to fix this in most backwards compatible way ...
Klaus: we have implicitely two kinds of clocks: for fixed / tunables we distinguish via a fly wheter the interval is given from the xml or from the FMU.
Pierre: for some clocks we have an absolute point of time, for others only intervals.

Patrick: I could make a proposal, but I need a decision in which direction to to go
Pierre: I would recommend to start with not allowing .... getInterval .... but we might end up in allowing it ...
Masoud: For which clocks to we need an absolute point of time?
Pierre: for non-periodic clocks you want an absolute point of time, but our API only gives an interval.
Klaus: this is the confusing part here that that we mix absolute and relative time
Pierre: forcing periodic and non-periodic clocks into the same API causes problems
Masoud: what is the problem why we should disallow it? and not just fix the qualifier definition
Pierre: ... first we have to fix the qualifier ...
Klaus: We could redefine the qualifiers
Pierre: We cannot allow calling without clarifying the return values.
Pierre: what about my proposal with returninig ... "changed" at the first call?
Klaus, Pierre: no!,
Klaus: this would have to be state dependent ... (e.g. initialization). I would go for unchanged. The importer has the information that it is a constant one.
Klaus: the simplest solution would be to not allow calling ....
Pierre: If the change is from setting outside this should be different from changes from within the FMU. This would be one way to handle this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants