Skip to content

ModelicaSystemCMD - use OMCPath #324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 72 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
c12c277
[OMCPath] add class
syntron Jun 28, 2025
908a239
[OMCPath] add implementation using OMC via sendExpression()
syntron Jun 27, 2025
00d016f
[OMCPath] add pytest (only docker at the moment)
syntron Jun 28, 2025
a449445
[OMCPath] TODO items
syntron Jun 28, 2025
17c9ee8
[test_OMCPath] mypy fix
syntron Jul 2, 2025
942635e
[test_OMCPath] fix end of file
syntron Jul 2, 2025
11b2524
[test_OMCPath] define test using OMCSessionZMQ() locally
syntron Jul 3, 2025
05b3c4d
add TODO - need to check Python versions
syntron Jul 6, 2025
79e118a
[test_OMCPath] activate docker based on test_docker
syntron Jul 6, 2025
e0cb453
[OMCPath] add more functionality and docstrings
syntron Jul 11, 2025
2b86442
[OMCPath] remove TODO entries
syntron Jul 11, 2025
a9fb9f9
[OMCPath] define limited compatibility for Python < 3.12
syntron Jul 11, 2025
fcb8571
[OMCSEssionZMQ] use OMCpath
syntron Jul 11, 2025
51b9160
[OMCSessionZMQ] create a tempdir using omcpath_tempdir()
syntron Jul 11, 2025
dd9afed
[OMCPath] fix mypy
syntron Jul 11, 2025
dc0393e
[OMCPath] add warning message for Python < 3.12
syntron Jul 11, 2025
6ff54d3
[OMCPath] try to make mypy happy ...
syntron Jul 11, 2025
c4323b3
[test_OMCPath] only for Python >= 3.12
syntron Jul 11, 2025
ec552dd
[test_OMCPath] update test
syntron Jul 11, 2025
3b99f2f
[OMCPath._omc_resolve] use sendExpression() with parsed=False
syntron Jul 12, 2025
a54b796
[test_OMCPath] cleanup; use the same code for local OMC and docker ba…
syntron Jul 12, 2025
02c40bc
[test_OMCPath] define test for WSL
syntron Jul 12, 2025
4feccf2
[test_OMCPath] use omcpath_tempdir() instead of hard-coded tempdir de…
syntron Jul 12, 2025
3625807
[OMCPath] spelling fix
syntron Jul 15, 2025
930cff1
[OMCPath] implementation version 3
syntron Jul 16, 2025
1de0e3b
[OMCSession*] fix flake8 (PyCharm likes the empty lines)
syntron Jul 16, 2025
8f38def
[OMCSessionZMQ] more generic definiton for omcpath_tempdir()
syntron Jul 16, 2025
9dc161b
[OMCPathCompatibility] mypy on github ...
syntron Jul 16, 2025
fd906cc
[OMCPathCompatibility] improve log messages
syntron Jul 16, 2025
90f8c98
[test_OMCPath] update
syntron Jul 16, 2025
b2a9190
[OMCPathReal] align exists() to the definition used in pathlib
syntron Jul 24, 2025
b11bfa9
[test_OMCPath] fix error
syntron Jul 26, 2025
26e73f6
[ModelicaSystem] update handling of work directory
syntron Jul 24, 2025
a9442b5
[ModelicaSystem] update handling of xml_file
syntron Jul 9, 2025
c4fabc5
[ModelicaSystem] replace ET.parse() with ET.ElementTree(ET.fromstring())
syntron Jul 9, 2025
3133f61
[ModelicaSystem._xmlparse] mypy fixes & cleanup
syntron Jul 10, 2025
33ea460
[ModelicaSystem] remove class variable _xml_file
syntron Jul 10, 2025
fa1f453
[ModelicaSystem] fix mypy warning - value can have different types in…
syntron Jul 12, 2025
250870c
[ModelicaSystem] do not use package csv
syntron Jul 26, 2025
66b9df3
[ModelicaSystem] create override file using pathlib.Path.write_text()
syntron Jul 26, 2025
a676435
[ModelicaSystem] update handling of override file
syntron Aug 5, 2025
38674e0
[OMCSessionRunData] add new class to store all information about a mo…
syntron Jul 24, 2025
0abdaf9
[OMCSessionRunData] use class to move run of model executable to OMSe…
syntron Jul 24, 2025
427ed71
[test_ModelicaSystemCmd] fix test
syntron Jul 25, 2025
7cd2cde
[OMCSessionRunData] add to __init__
syntron Jul 25, 2025
ec38c09
[test_ModelicaSystemCmd] fix test (again)
syntron Aug 12, 2025
646399f
[OMCProcess*] use pathlib
syntron Aug 6, 2025
6b55beb
Merge branch 'ModelicaSystem_workdir' into ModelicaSystemCmd_use_OMCPath
syntron Aug 16, 2025
0ffa36b
Merge branch 'ModelicaSystem_xml' into ModelicaSystemCmd_use_OMCPath
syntron Aug 16, 2025
3eb80f7
Merge branch 'ModelicaSystem_prepare_OMCPath' into ModelicaSystemCmd_…
syntron Aug 16, 2025
4384fa5
[ModelicaSystem] update handling of override file
syntron Aug 5, 2025
6617ab2
[ModelicaSystem] fix rebase fallout 2
syntron Jul 7, 2025
3022e65
[test_ModelicaSystem] fix test_customBuildDirectory()
syntron Jul 11, 2025
daa3caf
[ModelicaSystem] fix blank lines (flake8)
syntron Jul 22, 2025
f627daf
[test_optimization] fix due to OMCPath usage
syntron Aug 6, 2025
47dd995
[test_FMIExport] fix due to OMCPath usage
syntron Aug 6, 2025
d42753e
[ModelicaSystem] improve definition of getSolution
syntron Aug 9, 2025
229d624
[ModelicaSystem] use OMCPath for nearly all file system interactions
syntron Jul 11, 2025
087db3d
[ModelicaSystem] improve result file handling in simulate()
syntron Aug 9, 2025
100a060
Merge branch 'OMCSession_executable' into ModelicaSystemCmd_use_OMCPath
syntron Aug 16, 2025
ed1c2f6
Merge branch 'OMCProcess_pathlib' into ModelicaSystemCmd_use_OMCPath
syntron Aug 16, 2025
9695f9d
[ModelicaSystemCmd] use OMCPath for file system interactions
syntron Jul 11, 2025
197c2a4
[OMCProcessDockerHelper] implement omc_run_data_update()
syntron Jul 11, 2025
ed73392
[OMCProcessWSL] implement omc_run_data_update()
syntron Jul 11, 2025
6a998ba
[OMCProcessDockerHelper] define work directory in docker
syntron Jul 12, 2025
a0e6582
[OMCProcessWSL] define work directory for WSL
syntron Jul 12, 2025
9556ff7
[OMCSessionRunData] update docstring and comments
syntron Jul 12, 2025
c14b7fd
[ModelicaSystem] allow for non local execution, i.e. docker or WSL
syntron Jul 12, 2025
358e286
[test_ModelicaSystem] include test of ModelicaSystem using docker
syntron Jul 12, 2025
c953230
[OMCSessionZMQ] no session for omc_run_data_update()
syntron Jul 26, 2025
6b50282
[OMCProcess] remove session argument for OMCProcess.omc_run_data_upda…
syntron Jul 26, 2025
eea4a5d
[ModelicaSystem.buildModel] check if executable exists via ModelicaSy…
syntron Aug 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 164 additions & 148 deletions OMPython/ModelicaSystem.py

Large diffs are not rendered by default.

466 changes: 446 additions & 20 deletions OMPython/OMCSession.py

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion OMPython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"""

from OMPython.ModelicaSystem import LinearizationResult, ModelicaSystem, ModelicaSystemCmd, ModelicaSystemError
from OMPython.OMCSession import (OMCSessionCmd, OMCSessionException, OMCSessionZMQ,
from OMPython.OMCSession import (OMCSessionCmd, OMCSessionException, OMCSessionRunData, OMCSessionZMQ,
OMCProcessPort, OMCProcessLocal, OMCProcessDocker, OMCProcessDockerContainer,
OMCProcessWSL)

Expand All @@ -50,6 +50,7 @@

'OMCSessionCmd',
'OMCSessionException',
'OMCSessionRunData',
'OMCSessionZMQ',
'OMCProcessPort',
'OMCProcessLocal',
Expand Down
5 changes: 3 additions & 2 deletions tests/test_FMIExport.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import OMPython
import shutil
import os
import pathlib


def test_CauerLowPassAnalog():
mod = OMPython.ModelicaSystem(modelName="Modelica.Electrical.Analog.Examples.CauerLowPassAnalog",
lmodel=["Modelica"])
tmp = mod.getWorkDirectory()
tmp = pathlib.Path(mod.getWorkDirectory())
try:
fmu = mod.convertMo2Fmu(fileNamePrefix="CauerLowPassAnalog")
assert os.path.exists(fmu)
Expand All @@ -16,7 +17,7 @@ def test_CauerLowPassAnalog():

def test_DrumBoiler():
mod = OMPython.ModelicaSystem(modelName="Modelica.Fluid.Examples.DrumBoiler.DrumBoiler", lmodel=["Modelica"])
tmp = mod.getWorkDirectory()
tmp = pathlib.Path(mod.getWorkDirectory())
try:
fmu = mod.convertMo2Fmu(fileNamePrefix="DrumBoiler")
assert os.path.exists(fmu)
Expand Down
48 changes: 44 additions & 4 deletions tests/test_ModelicaSystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,36 @@
import os
import pathlib
import pytest
import sys
import tempfile
import numpy as np

skip_on_windows = pytest.mark.skipif(
sys.platform.startswith("win"),
reason="OpenModelica Docker image is Linux-only; skipping on Windows.",
)

skip_python_older_312 = pytest.mark.skipif(
sys.version_info < (3, 12),
reason="OMCPath(non-local) only working for Python >= 3.12.",
)


@pytest.fixture
def model_firstorder(tmp_path):
mod = tmp_path / "M.mo"
mod.write_text("""model M
def model_firstorder_content():
return ("""model M
Real x(start = 1, fixed = true);
parameter Real a = -1;
equation
der(x) = x*a;
end M;
""")


@pytest.fixture
def model_firstorder(tmp_path, model_firstorder_content):
mod = tmp_path / "M.mo"
mod.write_text(model_firstorder_content)
return mod


Expand Down Expand Up @@ -105,16 +121,40 @@ def test_customBuildDirectory(tmp_path, model_firstorder):
tmpdir = tmp_path / "tmpdir1"
tmpdir.mkdir()
m = OMPython.ModelicaSystem(filePath, "M", customBuildDirectory=tmpdir)
assert m.getWorkDirectory().resolve() == tmpdir.resolve()
assert pathlib.Path(m.getWorkDirectory()).resolve() == tmpdir.resolve()
result_file = tmpdir / "a.mat"
assert not result_file.exists()
m.simulate(resultfile="a.mat")
assert result_file.is_file()


@skip_on_windows
@skip_python_older_312
def test_getSolutions_docker(model_firstorder_content):
omcp = OMPython.OMCProcessDocker(docker="openmodelica/openmodelica:v1.25.0-minimal")
omc = OMPython.OMCSessionZMQ(omc_process=omcp)

modelpath = omc.omcpath_tempdir() / 'M.mo'
modelpath.write_text(model_firstorder_content)

file_path = pathlib.Path(modelpath)
mod = OMPython.ModelicaSystem(
fileName=file_path,
modelName="M",
omc_process=omc.omc_process,
)

_run_getSolutions(mod)


def test_getSolutions(model_firstorder):
filePath = model_firstorder.as_posix()
mod = OMPython.ModelicaSystem(filePath, "M")

_run_getSolutions(mod)


def _run_getSolutions(mod):
x0 = 1
a = -1
tau = -1 / a
Expand Down
9 changes: 6 additions & 3 deletions tests/test_ModelicaSystemCmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ def model_firstorder(tmp_path):
@pytest.fixture
def mscmd_firstorder(model_firstorder):
mod = OMPython.ModelicaSystem(fileName=model_firstorder.as_posix(), modelName="M")
mscmd = OMPython.ModelicaSystemCmd(runpath=mod.getWorkDirectory(), modelname=mod._model_name)
mscmd = OMPython.ModelicaSystemCmd(
session=mod._getconn,
runpath=mod.getWorkDirectory(),
modelname=mod._model_name,
)
return mscmd


Expand All @@ -32,8 +36,7 @@ def test_simflags(mscmd_firstorder):
with pytest.deprecated_call():
mscmd.args_set(args=mscmd.parse_simflags(simflags="-noEventEmit -noRestart -override=a=1,x=3"))

assert mscmd.get_cmd() == [
mscmd.get_exe().as_posix(),
assert mscmd.get_cmd_args() == [
'-noEventEmit',
'-override=b=2,a=1,x=3',
'-noRestart',
Expand Down
78 changes: 78 additions & 0 deletions tests/test_OMCPath.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import sys
import OMPython
import pytest

skip_on_windows = pytest.mark.skipif(
sys.platform.startswith("win"),
reason="OpenModelica Docker image is Linux-only; skipping on Windows.",
)

skip_python_older_312 = pytest.mark.skipif(
sys.version_info < (3, 12),
reason="OMCPath(non-local) only working for Python >= 3.12.",
)


def test_OMCPath_OMCSessionZMQ():
om = OMPython.OMCSessionZMQ()

_run_OMCPath_checks(om)

del om


def test_OMCPath_OMCProcessLocal():
omp = OMPython.OMCProcessLocal()
om = OMPython.OMCSessionZMQ(omc_process=omp)

_run_OMCPath_checks(om)

del om


@skip_on_windows
@skip_python_older_312
def test_OMCPath_OMCProcessDocker():
omcp = OMPython.OMCProcessDocker(docker="openmodelica/openmodelica:v1.25.0-minimal")
om = OMPython.OMCSessionZMQ(omc_process=omcp)
assert om.sendExpression("getVersion()") == "OpenModelica 1.25.0"

_run_OMCPath_checks(om)

del omcp
del om


@pytest.mark.skip(reason="Not able to run WSL on github")
@skip_python_older_312
def test_OMCPath_OMCProcessWSL():
omcp = OMPython.OMCProcessWSL(
wsl_omc='omc',
wsl_user='omc',
timeout=30.0,
)
om = OMPython.OMCSessionZMQ(omc_process=omcp)

_run_OMCPath_checks(om)

del omcp
del om


def _run_OMCPath_checks(om: OMPython.OMCSessionZMQ):
p1 = om.omcpath_tempdir()
p2 = p1 / 'test'
p2.mkdir()
assert p2.is_dir()
p3 = p2 / '..' / p2.name / 'test.txt'
assert p3.is_file() is False
assert p3.write_text('test')
assert p3.is_file()
assert p3.size() > 0
p3 = p3.resolve().absolute()
assert str(p3) == str((p2 / 'test.txt').resolve().absolute())
assert p3.read_text() == "test"
assert p3.is_file()
assert p3.parent.is_dir()
p3.unlink()
assert p3.is_file() is False
4 changes: 3 additions & 1 deletion tests/test_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ def test_optimization_example(tmp_path):

r = mod.optimize()
# it is necessary to specify resultfile, otherwise it wouldn't find it.
time, f, v = mod.getSolutions(["time", "f", "v"], resultfile=r["resultFile"])
resultfile_str = r["resultFile"]
resultfile_omcpath = mod._getconn.omcpath(resultfile_str)
time, f, v = mod.getSolutions(["time", "f", "v"], resultfile=resultfile_omcpath.as_posix())
assert np.isclose(f[0], 10)
assert np.isclose(f[-1], -10)

Expand Down
Loading