We have an ME FMU (related to #403, same original problem model, different MWE) that we're simulating with pyfmi (CVode), and we find that the outputs are not consistent -- the forces in a connection between one mass and an array of two MSL ElastoGaps do not sum to (approximately) zero when computed from the csv output results (postproc_sum)
Tracking the same sum in the Modelica model works as expected (internal_sum).
If elastoGap is not a 2-element array but a single object, the problem disappears, and postproc_sum becomes zero.
We simulated with pyfmi (mismatch O(1e0)), fmpy (mismatch O(1e-14)) and OMSimulator (mismatch O(1e-10)) to exclude the FMU as the source of the problem.
Expected result: postproc_sum built from pyfmi simulation outputs remains very small throughout the simulation time.
model SumMismatchMWE
Modelica.Mechanics.Translational.Components.ElastoGap[2] elastoGap(each s_rel(start = -0.1), each c = 100, each d = 0) annotation(
Placement(transformation(origin = {36, 14}, extent = {{-10, -10}, {10, 10}})));
Modelica.Mechanics.Translational.Sources.Position position annotation(
Placement(transformation(origin = {-40, 14}, extent = {{-10, -10}, {10, 10}})));
Modelica.Blocks.Sources.Sine sine(f = 1, continuous = true) annotation(
Placement(transformation(origin = {-70, 14}, extent = {{-10, -10}, {10, 10}})));
Modelica.Mechanics.Translational.Components.Mass[2] mass(each m = 1) annotation(
Placement(transformation(origin = {68, 14}, extent = {{-10, -10}, {10, 10}})));
Modelica.Mechanics.Translational.Components.Mass UL(m = 1) annotation(
Placement(transformation(origin = {-14, 14}, extent = {{-10, -10}, {10, 10}})));
Real internal_sum = UL.flange_b.f + elastoGap[1].flange_a.f + elastoGap[2].flange_a.f; // expected to be 0
equation
for i in 1:2 loop
connect(UL.flange_b, elastoGap[i].flange_a) annotation(
Line(points = {{-4, 14}, {26, 14}}, color = {0, 127, 0}));
connect(elastoGap[i].flange_b, mass[i].flange_a) annotation(
Line(points = {{46, 14}, {58, 14}}, color = {0, 127, 0}));;
end for;
connect(sine.y, position.s_ref) annotation(
Line(points = {{-59, 14}, {-52, 14}}, color = {0, 0, 127}));
connect(position.flange, UL.flange_a) annotation(
Line(points = {{-30, 14}, {-24, 14}}, color = {0, 127, 0}));
annotation(
uses(Modelica(version = "4.1.0")),
experiment(StartTime = 0, StopTime = 1, Tolerance = 1e-06, Interval = 0.002));
end SumMismatchMWE;
Python script producing the plots (for OMSimulator you have to set up a minimal SSP model)
"""Reproduce pyfmi force sum mismatch"""
from pathlib import Path
import fmpy
import matplotlib.pyplot as plt
import pandas as pd
import pyfmi
import assimulo
STOP_TIME = 0.25
def simulate_pyfmi(fmu_name):
print(f'{pyfmi.__version__=}') # 2.21.0
print(f'{assimulo.__version__=}') # 3.7.3
model = pyfmi.load_fmu(fmu_name, kind='ME')
opts = model.simulate_options()
opts["logging"] = True
opts["result_handling"] = "csv"
print(opts)
model.simulate(final_time=STOP_TIME, options=opts)
print("Finished pyfmi simulation")
def simulate_fmpy(fmu_name):
print(f'{fmpy.__version__=}')
fmpy.dump(fmu_name)
outputs = [
'UL.flange_b.f',
'elastoGap[1].flange_a.f',
'elastoGap[2].flange_a.f',
'internal_sum',
]
result = fmpy.simulate_fmu(fmu_name, stop_time=STOP_TIME, fmi_type='ModelExchange', solver='CVode', output=outputs)
fmpy.write_csv(Path(fmu_name).stem + '_result_fmpy.csv', result)
def postproc(resultfile, prefix='eHydroCOMHDRingValveSystem.SV.', fig_title = ''):
df = pd.read_csv(resultfile, index_col='time')
df['postproc_sum'] = df[prefix + 'UL.flange_b.f'] + df[prefix + 'elastoGap[1].flange_a.f'] + df[prefix + 'elastoGap[2].flange_a.f']
df['abs_node_sum'] = abs(df['postproc_sum'])
fig, axes = plt.subplots(nrows=3, ncols=1, sharex=True)
fig.suptitle(fig_title)
axes[0] = df.plot.line(y=[prefix + 'UL.flange_b.f',
prefix + 'elastoGap[1].flange_a.f',
prefix + 'elastoGap[2].flange_a.f'],
ax=axes[0],
)
axes[1] = df.plot.line(y=['postproc_sum', prefix + 'internal_sum'], ax=axes[1])
axes[2] = df.plot.line(y='abs_node_sum', logy=True, ax=axes[2])
return fig
if __name__ == '__main__':
simulate_pyfmi('SumMismatchMWE.fmu')
postproc('SumMismatchMWE_result.csv', prefix='', fig_title='pyfmi')
simulate_fmpy('SumMismatchMWE.fmu')
postproc('SumMismatchMWE_result_fmpy.csv', prefix='', fig_title='fmpy')
#postproc('mismatch_res.csv', prefix='mismatch.Root.SumMismatchMWE.', fig_title='OMSimulator') # OMSimulator
plt.show()
Versions:
pyfmi='2.21.0'
assimulo='3.7.3'
OpenModelica v1.27.0-dev-330-g5f16e75445
Windows 11
We have an ME FMU (related to #403, same original problem model, different MWE) that we're simulating with pyfmi (CVode), and we find that the outputs are not consistent -- the forces in a connection between one mass and an array of two MSL ElastoGaps do not sum to (approximately) zero when computed from the csv output results (
postproc_sum)Tracking the same sum in the Modelica model works as expected (
internal_sum).If
elastoGapis not a 2-element array but a single object, the problem disappears, andpostproc_sumbecomes zero.We simulated with pyfmi (mismatch O(1e0)), fmpy (mismatch O(1e-14)) and OMSimulator (mismatch O(1e-10)) to exclude the FMU as the source of the problem.
Expected result:
postproc_sumbuilt from pyfmi simulation outputs remains very small throughout the simulation time.Python script producing the plots (for OMSimulator you have to set up a minimal SSP model)
Versions:
pyfmi='2.21.0'
assimulo='3.7.3'
OpenModelica v1.27.0-dev-330-g5f16e75445
Windows 11