Skip to content

Commit 3cacf04

Browse files
authored
[ModelicaSystem] make convertFmu2Mo() useable (#351)
* [ModelicaSystem] update convertMo2Fmu() and convertFmu2Mo() to use pathlib.Path() * [ModelicaSystem] define convertFmu2Mo() as entry point like definition() * rename fmuName => fmu * [ModelicaSystem] fix definition of fmu_path * [ModelicaSystem] fix path in convertFmu2Mo() * [test_FMIImport] running example / test for convertFmu2Mo() * [ModelicaSystem] replace pathlib by OMCPath * [ModelicaSystem] fix _getconn => _session
1 parent 6b44870 commit 3cacf04

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

OMPython/ModelicaSystem.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,7 +1631,7 @@ def convertMo2Fmu(
16311631
fmuType: str = "me_cs",
16321632
fileNamePrefix: Optional[str] = None,
16331633
includeResources: bool = True,
1634-
) -> str:
1634+
) -> OMCPath:
16351635
"""Translate the model into a Functional Mockup Unit.
16361636
16371637
Args:
@@ -1658,15 +1658,19 @@ def convertMo2Fmu(
16581658
properties = (f'version="{version}", fmuType="{fmuType}", '
16591659
f'fileNamePrefix="{fileNamePrefix}", includeResources={includeResourcesStr}')
16601660
fmu = self._requestApi(apiName='buildModelFMU', entity=self._model_name, properties=properties)
1661+
fmu_path = self._session.omcpath(fmu)
16611662

16621663
# report proper error message
1663-
if not os.path.exists(fmu):
1664-
raise ModelicaSystemError(f"Missing FMU file: {fmu}")
1664+
if not fmu_path.is_file():
1665+
raise ModelicaSystemError(f"Missing FMU file: {fmu_path.as_posix()}")
16651666

1666-
return fmu
1667+
return fmu_path
16671668

16681669
# to convert FMU to Modelica model
1669-
def convertFmu2Mo(self, fmuName): # 20
1670+
def convertFmu2Mo(
1671+
self,
1672+
fmu: os.PathLike,
1673+
) -> OMCPath:
16701674
"""
16711675
In order to load FMU, at first it needs to be translated into Modelica model. This method is used to generate
16721676
Modelica model from the given FMU. It generates "fmuName_me_FMU.mo".
@@ -1675,13 +1679,24 @@ def convertFmu2Mo(self, fmuName): # 20
16751679
>>> convertFmu2Mo("c:/BouncingBall.Fmu")
16761680
"""
16771681

1678-
fileName = self._requestApi(apiName='importFMU', entity=fmuName)
1682+
fmu_path = self._session.omcpath(fmu)
1683+
1684+
if not fmu_path.is_file():
1685+
raise ModelicaSystemError(f"Missing FMU file: {fmu_path.as_posix()}")
1686+
1687+
filename = self._requestApi(apiName='importFMU', entity=fmu_path.as_posix())
1688+
filepath = self._work_dir / filename
16791689

16801690
# report proper error message
1681-
if not os.path.exists(fileName):
1682-
raise ModelicaSystemError(f"Missing file {fileName}")
1691+
if not filepath.is_file():
1692+
raise ModelicaSystemError(f"Missing file {filepath.as_posix()}")
1693+
1694+
self.model(
1695+
name=f"{fmu_path.stem}_me_FMU",
1696+
file=filepath,
1697+
)
16831698

1684-
return fileName
1699+
return filepath
16851700

16861701
def optimize(self) -> dict[str, Any]:
16871702
"""Perform model-based optimization.

tests/test_FMIImport.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import numpy as np
2+
import os
3+
import pytest
4+
import shutil
5+
6+
import OMPython
7+
8+
9+
@pytest.fixture
10+
def model_firstorder(tmp_path):
11+
mod = tmp_path / "M.mo"
12+
mod.write_text("""model M
13+
Real x(start = 1, fixed = true);
14+
parameter Real a = -1;
15+
equation
16+
der(x) = x*a;
17+
end M;
18+
""")
19+
return mod
20+
21+
22+
def test_FMIImport(model_firstorder):
23+
filePath = model_firstorder.as_posix()
24+
25+
# create model & simulate it
26+
mod1 = OMPython.ModelicaSystem()
27+
mod1.model(file=filePath, name="M")
28+
mod1.simulate()
29+
30+
# create FMU & check
31+
fmu = mod1.convertMo2Fmu(fileNamePrefix="M")
32+
assert os.path.exists(fmu)
33+
34+
# import FMU & check & simulate
35+
# TODO: why is '--allowNonStandardModelica=reinitInAlgorithms' needed? any example without this possible?
36+
mod2 = OMPython.ModelicaSystem(commandLineOptions=['--allowNonStandardModelica=reinitInAlgorithms'])
37+
mo = mod2.convertFmu2Mo(fmu=fmu)
38+
assert os.path.exists(mo)
39+
40+
mod2.simulate()
41+
42+
# get and verify result
43+
res1 = mod1.getSolutions(['time', 'x'])
44+
res2 = mod2.getSolutions(['time', 'x'])
45+
46+
# check last value for time
47+
assert res1[0][-1] == res2[0][-1] == 1.0
48+
# check last value for x
49+
assert np.isclose(res1[1][-1], 0.3678794515) # 0.36787945153397683
50+
assert np.isclose(res2[1][-1], 0.3678794515) # 0.3678794515707647
51+
52+
# cleanup
53+
tmp2 = mod1.getWorkDirectory()
54+
shutil.rmtree(tmp2, ignore_errors=True)
55+
56+
tmp2 = mod2.getWorkDirectory()
57+
shutil.rmtree(tmp2, ignore_errors=True)

0 commit comments

Comments
 (0)