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.
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.
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