Search code examples
pythonsimulationfmisiemens-nx

Getting NaN values from the model using FMPy


I’m running an FMU export from Simcenter that runs on 5e-7 step-size in FMPy. However, after a few steps the FMU starts returning NaN values. My expectation is that this is due to the way I am using FMPy, but I am unable to solve it until now.

  1. Which variables within FMPy should I use, considering the use-case (read below)?
  2. Anybody who has had NaN values, and knows how to solve this?

The FMU from Simcenter runs on a container within Azure, and receives input from and sends output to a local Simulink model. There’s basically a recurrent feedback loop between the two models. For my project, I need to run the FMU only for 1 step at a time, return result to Simulink and keep FMU active for future input that would simulate the FMU further. (for implementation of running FMU 1 step at a time with FMPy I’m using continue_simulation.py example from https://github.com/CATIA-Systems/FMPy/blob/main/fmpy/examples/continue_simulation.py.)

The local Simulink model and the Simcenter model run on different step-sizes. Therefore, we have included a rate-transition within the Simulink model. When we run the FMU directly within Simulink, this runs as expected. However, once I change the FMU into a Matlab function block, which is rerouted to the container on our platform, it starts returning NaN values.

Currently have the following variables configured within FMPY simulate_fmu():

filename
model_description
fmu_instance
input
initialize=False
start_time=0 (will be 5e-7 next run)
stop_time=5e-7 (will be 1e-6 next run)
step_size=5e-7
terminate=False
set_stop_time=False

The issue I’m facing now is when using 5e-7 step-size and 5e-7 stop-time, the FMU starts returning drastically different values comparing to same FMU running in Simulink from the 7th step and on the 10th step reaches NaN values as outputs.


Solution

  • I found the solution. It was to stop using simulate_fmu() function that does quite some things under the hood and instead use the functions, that simulate_fmu() uses, myself to avoid using extra things that I did not need (also helped to better understand how FMPy works). This resulted in the model returning expected values and not NaN values anymore.

    I used the example code from custom_input.py FMPy docs (https://github.com/CATIA-Systems/FMPy/blob/main/fmpy/examples/custom_input.py)

    My custom function to run a step(s) of FMU now looks like this:

    def set_input(self, inputs_array_values, step_size, interval):
        # Proceed with running the step(s)
        stop_time = self._current_simulation_time + interval
        while self._current_simulation_time < stop_time:
            # set the input
            print(f"value references: {self._vrs_inputs.values()}, input values: {inputs_array_values}")
            self._fmu.setReal(self._vrs_inputs.values(), inputs_array_values)
            # perform one step
            self._fmu.doStep(currentCommunicationPoint=self._current_simulation_time, communicationStepSize=step_size)
            # advance the time
            self._current_simulation_time += interval
            print(f"current simulation time: {self._current_simulation_time}")
    
        # return without delay. 1 step delay will be created in Simulink as Unit Delay is required to properly run the simulation by fixing algebraic loop
        outputs = []
        outputs = self._fmu.getReal(self._vrs_outputs.values())
        outputs.insert(0, float(self._current_simulation_time))
        row = tuple(outputs)
        self._results.append(str(row))
    
        return row