Opened 10 years ago

Closed 10 years ago

#2767 closed defect (fixed)

fmi2GetDerivatives shifts value references by -1 when calling getReal of FMU

Reported by: rfranke@… Owned by: Willi Braun
Priority: critical Milestone: 1.9.1
Component: FMI Version: trunk
Keywords: Cc: Willi Braun

Description

First of all: thank you for the fast processing of #2762!

Now the exported FMU version 2.0 shall run in another environment (github.com/omuses/hqp). According to modelDescription.xml the FMU has the following variables:

valueReference   name
0                y1
1                y2
2                der(y1)
3                der(y2)
4                u           local!!???
5                p
6                y1_start
7                y2_start

When the environment calls fmi2GetDerivatives, then OpenModelica calls the getReal function of the generated DIC_FMU.c with the vr's 1 and 2 -- it must be 2 and 3! Can you please check your implementation of fmi2GetDerivatives?

Btw.: it's a pitty that the fmi-functions, such as fmi2GetDerivatives are not part of the exported C-code. This would simplify debugging and potential porting to an embedded target platform.

Moreover: this week a change has been introduced that now lets the input u appear with causality "local" in modelDescription.xml!? Can you please check as well?

Attachments (1)

DIC.mo (292 bytes ) - added by Adeel Asghar 10 years ago.

Download all attachments as: .zip

Change History (9)

comment:1 by Rüdiger Franke, 10 years ago

Forget the last paragraph "Moreover ..." in the ticket above. ... Attempting to work around #2763, I had removed the input keyword in OMEdit and OMEdit saved the changed model when simulating it ...

Btw.: I'm using OpenModelica 1.9.1+dev (r21721).

Now all FMU functions, except fmi2GetDerivatives, seem to return the correct values.

However, the derivatives appear to be constant during the simulation. This is because the functions DIC_eqFunction_* with the model equations in the exported file DIC.c get only called once at model initialization. Afterwards only DIC_output_function is called during the simulation.

The FMU simulates (and optimizes) correctly after having fixed the problems with wrong fmi2GetDerivatives and DIC_eqFunction_*!

Two more problems became visible though:

The function getReal in the exported file DIC_FMU.c returns fmi2Error per default, which results in a value of 3.0!?

  fmi2Real getReal(ModelInstance* comp, const fmi2ValueReference vr) {
    switch (vr) {
        ...
        default:
            return fmi2Error;
    }
  }

Attempting to instantiate the FMU a second time in the same process leads to a crash, which most likely is caused by wrong management of dynamic memory.

Please consider two generals improvements for the FMI2 export:

  1. It would really simplify the debugging if the fmi2-functions, like fmi2Instantiate, fmi2GetDerivatives, etc. would belong to the exported C-code, in order to being able to run it in a debugger together with a regular nightly build.
  1. Having no debugger, one an use logging. Unfortunately the loggingOn argument of the function fmi2Instantiate doesn't appear to do anything. Meaning that I have to manually add log messages to the exported C-Code, again and again if I change the model and re-export it.

What is your preferred practice when developing and debugging the FMI2 export?

comment:2 by Rüdiger Franke, 10 years ago

Meanwhile I found the fmi2 functions in /usr/include/omc/c/fmi2/fmu2_model_interface.c. It runs with debugging and with logging now.

The function fmi2GetDerivatives obtaines the vr's for derivatives with (see fmu2_model_interface.c, L791):

    fmi2ValueReference vr = vrStates[i] + 1;

The double integrator example above works with:

    fmi2ValueReference vr = NUMBER_OF_STATES + i;

The crash happens if fmi2Reset is called after fmi2Terminate. fmi2Reset calls the function setAllVarsToStart from libSimulationRuntimeC.so, which crashes. Can it be that fmi2Terminate frees too much memory, which should be delayed until fmi2FreeInstance?

The remaining question is, why the evaluation of the model equations is not triggered in ContinuousTimeMode after initialization ... Shouldn't the functions fmi2SetTime/Real/ContinuousStates set a flag, which results in an evaluation of the model before the next fmi2Get... returns? What else is needed to trigger the evaluation?

comment:3 by rfranke@…, 10 years ago

The following patch adapts fmu2_model_interface.c to fmu1_model_interface.c, fixing the value references for derivatives (lines 53 and 793) and adding the evaluation of the model equations (line 790). This basically solves this ticket.

  • fmu2_model_interface.c

    old new  
    5050// array of value references of states
    5151#if NUMBER_OF_REALS>0
    5252fmi2ValueReference vrStates[NUMBER_OF_STATES] = STATES;
     53fmi2ValueReference vrStatesDerivatives[NUMBER_OF_STATES] = STATESDERIVATIVES;
    5354#endif
    5455
    5556// ---------------------------------------------------------------------------
     
    786787    return fmi2Error;
    787788  if (nullPointer(comp, "fmi2GetDerivatives", "derivatives[]", derivatives))
    788789    return fmi2Error;
     790  comp->fmuData->callback->functionODE(comp->fmuData);
    789791#if NUMBER_OF_STATES>0
    790792  for (i = 0; i < nx; i++) {
    791     fmi2ValueReference vr = vrStates[i] + 1;
     793    fmi2ValueReference vr = vrStatesDerivatives[i];
    792794    derivatives[i] = getReal(comp, vr); // to be implemented by the includer of this file
    793795    FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetDerivatives: #r%d# = %.16g", vr, derivatives[i])
    794796  }

Open issues that arose from the treatment of this ticket are the strange implementation of getReal (possibly returning fmi2Error as fmi2Real) and the crash if fmi2Reset is called after fmi2Terminate.

comment:4 by Adeel Asghar, 10 years ago

Cc: Willi Braun added
Owner: changed from Adeel Asghar to Willi Braun
Status: newassigned

Following things fixed in r22404,

  • Fixed fmi2GetDerivatives.
  • getReal now only returns fmi1Real/fmi2Real.
  • Added LogCategories to modelDescription.xml

If you call fmi2SetDebugLogging then you should read the log categories from the modelDescription.xml file and pass it to that function to enable logging. If you are not calling this function then loggingOn parameter of fmi2Instantiate function will work.

I think the only issue left is,
Moreover: this week a change has been introduced that now lets the input u appear with causality "local" in modelDescription.xml!? Can you please check as well?
Perhaps Willi will get some time to fix it.

by Adeel Asghar, 10 years ago

Attachment: DIC.mo added

comment:5 by Rüdiger Franke, 10 years ago

Sounds good. Looking forward to getting the next nightly build, in order to try it out!

The "local" thing was my fault. I had changed

   input Real u (start = -2)

to

   Real u = -2

in OMEdit, in order to get a value in the simulation (see also #2763). OMEdit automatically saved the changed model before the simulation. Meanwhile I disabled this auto saving in my Preferences of OMEdit.

The only remaining issue is the crash if fmi2Reset is called after fmi2Terminate. This happens if more than one simulation is performed in a process keeping the model loaded. Can it be that fmi2Terminate releases too much memory? Or shall I open a separate ticket for this?

comment:6 by Adeel Asghar, 10 years ago

Try r22422. I tried to reinitialize the data when fmi2Reset is called.

I am not sure if it will work fine but lets give it a try. I don't have a testcase to test this scenario.

comment:7 by Rüdiger Franke, 10 years ago

It works with the new nightly OpenModelica 1.9.1+dev (r22423)!

If you want to run a test case, I added the example to the HQP solver, see:

https://github.com/omuses/hqp/commit/ad90db6bc26094019e8fa515685ed2b707855df2

You might:

$ git clone https://github.com/omuses/hqp.git
$ cd hqp
$ ./configure
$ make
$ cd odc
$ ./runtk dic_fmu

The last command will invoke omc to compile DIC.fmu from DIC.mo, run an optimization and plot the results -- there are some dependencies like gcc and tcl-dev for the compilation of the solver as well as omc for the compilation of the model and optionally blt for the plotting.

Multiple runs in the same process can be performed with the Tcl command:

$ ./odc
$ time {source dic_fmu.tcl} 10

to perform 10 runs and get the time per run.

Thank's a lot!

P.S.: eventually the model specific definitions in the drivers dic_fmu.tcl and dic_fmu_est.tcl should go into custom annotations. Then one will be able to specify the complete optimization or estimation together with the model in Modelica.

comment:8 by Adeel Asghar, 10 years ago

Resolution: fixed
Status: assignedclosed

If it works fine then its ok :).

If you have problems then open a new ticket about it and then I will try to setup the test case.

Note: See TracTickets for help on using tickets.