Skip to content

Events are not detected for FMI 3.0 co-simulation #1609

Description

@AnHeuermann

Description

OMSimulator never asks an FMI 3.0 co-simulation FMU to report its events, so all
events that happen inside fmi3DoStep are lost. The result file only contains
the communication points and the discontinuity is smeared over one step instead
of being stored as two data points.

Stair3.fmu declares everything that is needed for this to work:

<CoSimulation ... canHandleVariableCommunicationStepSize="true"
                  providesIntermediateUpdate="true"
                  canReturnEarlyAfterIntermediateUpdate="true"
                  hasEventMode="true" />

but OMSimulator opts out of event mode at instantiation and ignores the event
flags returned by fmi3DoStep, see What is missing below.

This is a follow-up to #1603. The model-exchange side is fixed there; this issue
is only about co-simulation. Note that FMI 2.0 co-simulation cannot be fixed —
it has no event mode, no early return and no way to observe an event inside
fmi2DoStep — so this is specific to FMI 3.0.

Steps to reproduce the behavior

$ cd /path/to/OMSimulator/testsuite/reference-fmus/3.0
$ python3 Stair.py
Loading FMI version 3...
info:    Result file: Stair-cs3.mat (bufferSize=10)
error:   [compareSeries] ResultReader::compareSeries: different number of events: 9 != 0
signal counter is not equal

The reference testsuite/references/Stair-cs.mat holds 9 events (the counter
increments at t = 1, 2, ..., 9), the result file holds none.

Inspecting Stair-cs3.mat shows the plain communication grid, no data points
sharing a time stamp:

t       : 0.0  0.2  0.4  0.6  0.8  1.0  1.2  ...
counter : 1    1    1    1    1    2    2    ...

Expected behavior

At every event the result file should contain two data points with the same
time stamp, holding the value before and after the event:

t       : ...  0.8  1.0  1.0  1.2  ...
counter : ...  1    1    2    2    ...

i.e. the same trajectory the model-exchange run already produces after #1603.

What is missing

  1. Event mode is not requested at instantiation.
    ComponentFMU3CS::instantiate()
    hardcodes both eventModeUsed and earlyReturnAllowed to fmi3False:

    if(!fmi3_instantiateCoSimulation(fmu, fmi3False, fmi3True, fmi3False, fmi3False, NULL, 0, fmu, omsfmi3logger, NULL))

    These should be enabled when the FMU declares hasEventMode and
    canReturnEarlyAfterIntermediateUpdate.

  2. The event flags of fmi3DoStep are discarded.
    ComponentFMU3CS::stepUntil()
    already retrieves them and then throws all four away — only fmi3Discard is
    acted on:

    bool eventEncountered, terminateSimulation, earlyReturn;
    double lastT;
    
    while (time < stopTime)
    {
      fmi3Status status = fmi3_doStep(fmu, time, hdef, fmi3True, &eventEncountered, &terminateSimulation, &earlyReturn, &lastT);
      time += hdef;
      ...
    }

    On eventEncountered it should set time = lastT, emit the lhs, run
    fmi3_enterEventMode()fmi3_updateDiscreteStates() (event iteration) →
    fmi3_enterStepMode(), emit the rhs, and continue stepping from lastT.

All three fmi4c entry points already exist
(fmi3_enterEventMode, fmi3_updateDiscreteStates, fmi3_enterStepMode in
3rdParty/fmi4c/include/fmi4c.h), and the equivalent loop is already
implemented for model exchange in
SystemSC3.cpp together with
ComponentFMU3ME::doEventIteration(),
so this is mostly a matter of porting that logic into the CS component.

Notes

The failure only becomes visible with the event-aware
oms_compareSimulationResults(). The previous implementation interpolated
across events and silently accepted a result file without them, which is why
this test used to pass.

Version and OS

  • Version: OMSimulator v3.0.0.post152-g810613a-linux-debug
  • OS: Ubuntu 26.04 LTS

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions