Skip to content
1,903 changes: 1,090 additions & 813 deletions OMPython/ModelicaSystem.py

Large diffs are not rendered by default.

1,207 changes: 825 additions & 382 deletions OMPython/OMCSession.py

Large diffs are not rendered by default.

46 changes: 40 additions & 6 deletions OMPython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,37 @@
from OMPython.ModelicaSystem import (
LinearizationResult,
ModelicaSystem,
ModelicaSystemCmd,
ModelicaSystemOMC,
ModelExecutionCmd,
ModelicaSystemDoE,
ModelicaDoEOMC,
ModelicaSystemError,
ModelicaSystemRunner,
ModelicaDoERunner,

doe_get_solutions,
)
from OMPython.OMCSession import (
OMPathABC,
OMCPath,
OMCSession,

OMSessionRunner,

OMCSessionABC,

ModelExecutionData,
ModelExecutionException,

OMCSessionCmd,
OMCSessionDocker,
OMCSessionDockerContainer,
OMCSessionException,
OMCSessionLocal,
OMCSessionPort,
OMCSessionRunData,

OMPathRunnerBash,
OMPathRunnerLocal,

OMCSessionWSL,
OMCSessionZMQ,
)
Expand All @@ -36,21 +53,38 @@
__all__ = [
'LinearizationResult',

'ModelExecutionData',
'ModelExecutionException',

'ModelicaSystem',
'ModelicaSystemCmd',
'ModelicaSystemOMC',
'ModelExecutionCmd',
'ModelicaSystemDoE',
'ModelicaDoEOMC',
'ModelicaSystemError',

'ModelicaSystemRunner',
'ModelicaDoERunner',

'OMPathABC',
'OMCPath',

'OMCSession',
'OMSessionRunner',

'OMCSessionABC',

'doe_get_solutions',

'OMCSessionCmd',
'OMCSessionDocker',
'OMCSessionDockerContainer',
'OMCSessionException',
'OMCSessionPort',
'OMCSessionLocal',
'OMCSessionRunData',

'OMPathRunnerBash',
'OMPathRunnerLocal',

'OMCSessionWSL',
'OMCSessionZMQ',
]
4 changes: 2 additions & 2 deletions tests/test_FMIExport.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def test_CauerLowPassAnalog():
mod = OMPython.ModelicaSystem()
mod = OMPython.ModelicaSystemOMC()
mod.model(
model_name="Modelica.Electrical.Analog.Examples.CauerLowPassAnalog",
libraries=["Modelica"],
Expand All @@ -20,7 +20,7 @@ def test_CauerLowPassAnalog():


def test_DrumBoiler():
mod = OMPython.ModelicaSystem()
mod = OMPython.ModelicaSystemOMC()
mod.model(
model_name="Modelica.Fluid.Examples.DrumBoiler.DrumBoiler",
libraries=["Modelica"],
Expand Down
4 changes: 2 additions & 2 deletions tests/test_FMIImport.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def model_firstorder(tmp_path):

def test_FMIImport(model_firstorder):
# create model & simulate it
mod1 = OMPython.ModelicaSystem()
mod1 = OMPython.ModelicaSystemOMC()
mod1.model(
model_file=model_firstorder,
model_name="M",
Expand All @@ -35,7 +35,7 @@ def test_FMIImport(model_firstorder):

# import FMU & check & simulate
# TODO: why is '--allowNonStandardModelica=reinitInAlgorithms' needed? any example without this possible?
mod2 = OMPython.ModelicaSystem(command_line_options=['--allowNonStandardModelica=reinitInAlgorithms'])
mod2 = OMPython.ModelicaSystemOMC(command_line_options=['--allowNonStandardModelica=reinitInAlgorithms'])
mo = mod2.convertFmu2Mo(fmu=fmu)
assert os.path.exists(mo)

Expand Down
26 changes: 13 additions & 13 deletions tests/test_ModelicaSystemDoE.py → tests/test_ModelicaDoEOMC.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,75 +51,75 @@ def param_doe() -> dict[str, list]:
return param


def test_ModelicaSystemDoE_local(tmp_path, model_doe, param_doe):
def test_ModelicaDoEOMC_local(tmp_path, model_doe, param_doe):
tmpdir = tmp_path / 'DoE'
tmpdir.mkdir(exist_ok=True)

mod = OMPython.ModelicaSystem()
mod = OMPython.ModelicaSystemOMC()
mod.model(
model_file=model_doe,
model_name="M",
)

doe_mod = OMPython.ModelicaSystemDoE(
doe_mod = OMPython.ModelicaDoEOMC(
mod=mod,
parameters=param_doe,
resultpath=tmpdir,
simargs={"override": {'stopTime': '1.0'}},
)

_run_ModelicaSystemDoe(doe_mod=doe_mod)
_run_ModelicaDoEOMC(doe_mod=doe_mod)


@skip_on_windows
@skip_python_older_312
def test_ModelicaSystemDoE_docker(tmp_path, model_doe, param_doe):
def test_ModelicaDoEOMC_docker(tmp_path, model_doe, param_doe):
omcs = OMPython.OMCSessionDocker(docker="openmodelica/openmodelica:v1.25.0-minimal")
omversion = omcs.sendExpression("getVersion()")
assert isinstance(omversion, str) and omversion.startswith("OpenModelica")

mod = OMPython.ModelicaSystem(
mod = OMPython.ModelicaSystemOMC(
session=omcs,
)
mod.model(
model_file=model_doe,
model_name="M",
)

doe_mod = OMPython.ModelicaSystemDoE(
doe_mod = OMPython.ModelicaDoEOMC(
mod=mod,
parameters=param_doe,
simargs={"override": {'stopTime': '1.0'}},
)

_run_ModelicaSystemDoe(doe_mod=doe_mod)
_run_ModelicaDoEOMC(doe_mod=doe_mod)


@pytest.mark.skip(reason="Not able to run WSL on github")
@skip_python_older_312
def test_ModelicaSystemDoE_WSL(tmp_path, model_doe, param_doe):
def test_ModelicaDoEOMC_WSL(tmp_path, model_doe, param_doe):
omcs = OMPython.OMCSessionWSL()
omversion = omcs.sendExpression("getVersion()")
assert isinstance(omversion, str) and omversion.startswith("OpenModelica")

mod = OMPython.ModelicaSystem(
mod = OMPython.ModelicaSystemOMC(
session=omcs,
)
mod.model(
model_file=model_doe,
model_name="M",
)

doe_mod = OMPython.ModelicaSystemDoE(
doe_mod = OMPython.ModelicaDoEOMC(
mod=mod,
parameters=param_doe,
simargs={"override": {'stopTime': '1.0'}},
)

_run_ModelicaSystemDoe(doe_mod=doe_mod)
_run_ModelicaDoEOMC(doe_mod=doe_mod)


def _run_ModelicaSystemDoe(doe_mod):
def _run_ModelicaDoEOMC(doe_mod):
doe_count = doe_mod.prepare()
assert doe_count == 16

Expand Down
158 changes: 158 additions & 0 deletions tests/test_ModelicaDoERunner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import pathlib
import sys

import numpy as np
import pytest

import OMPython

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_doe(tmp_path: pathlib.Path) -> pathlib.Path:
# see: https://trac.openmodelica.org/OpenModelica/ticket/4052
mod = tmp_path / "M.mo"
# TODO: update for bool and string parameters; check if these can be used in DoE
mod.write_text("""
model M
parameter Integer p=1;
parameter Integer q=1;
parameter Real a = -1;
parameter Real b = -1;
Real x[p];
Real y[q];
equation
der(x) = a * fill(1.0, p);
der(y) = b * fill(1.0, q);
end M;
""")
return mod


@pytest.fixture
def param_doe() -> dict[str, list]:
param = {
# simple
'a': [5, 6],
'b': [7, 8],
}
return param


def test_ModelicaDoERunner_ModelicaSystemOMC(tmp_path, model_doe, param_doe):
tmpdir = tmp_path / 'DoE'
tmpdir.mkdir(exist_ok=True)

mod = OMPython.ModelicaSystemOMC()
mod.model(
model_file=model_doe,
model_name="M",
)

resultfile_mod = mod.getWorkDirectory() / f"{mod.get_model_name()}_res_mod.mat"
_run_simulation(mod=mod, resultfile=resultfile_mod, param=param_doe)

doe_mod = OMPython.ModelicaDoERunner(
mod=mod,
parameters=param_doe,
resultpath=tmpdir,
)

_run_ModelicaDoERunner(doe_mod=doe_mod)

_check_runner_result(mod=mod, doe_mod=doe_mod)


def test_ModelicaDoERunner_ModelicaSystemRunner(tmp_path, model_doe, param_doe):
tmpdir = tmp_path / 'DoE'
tmpdir.mkdir(exist_ok=True)

mod = OMPython.ModelicaSystemOMC()
mod.model(
model_file=model_doe,
model_name="M",
)

resultfile_mod = mod.getWorkDirectory() / f"{mod.get_model_name()}_res_mod.mat"
_run_simulation(mod=mod, resultfile=resultfile_mod, param=param_doe)

# run the model using only the runner class
omcs = OMPython.OMSessionRunner(
version=mod.get_session().get_version(),
)
modr = OMPython.ModelicaSystemRunner(
session=omcs,
work_directory=mod.getWorkDirectory(),
)
modr.setup(
model_name="M",
)
doe_mod = OMPython.ModelicaDoERunner(
mod=modr,
parameters=param_doe,
resultpath=tmpdir,
)

_run_ModelicaDoERunner(doe_mod=doe_mod)

_check_runner_result(mod=mod, doe_mod=doe_mod)


def _run_simulation(mod, resultfile, param):
simOptions = {"stopTime": 1.0, "stepSize": 0.1, "tolerance": 1e-8}
mod.setSimulationOptions(**simOptions)
mod.simulate(resultfile=resultfile)

assert resultfile.exists()


def _run_ModelicaDoERunner(doe_mod):
doe_count = doe_mod.prepare()
assert doe_count == 4

doe_def = doe_mod.get_doe_definition()
assert isinstance(doe_def, dict)
assert len(doe_def.keys()) == doe_count

doe_cmd = doe_mod.get_doe_command()
assert isinstance(doe_cmd, dict)
assert len(doe_cmd.keys()) == doe_count

doe_status = doe_mod.simulate()
assert doe_status is True


def _check_runner_result(mod, doe_mod):
doe_cmd = doe_mod.get_doe_command()
doe_def = doe_mod.get_doe_definition()

doe_sol = OMPython.doe_get_solutions(
msomc=mod,
resultpath=doe_mod.get_resultpath(),
doe_def=doe_def,
)
assert isinstance(doe_sol, dict)
assert len(doe_sol.keys()) == len(doe_cmd.keys())

assert sorted(doe_def.keys()) == sorted(doe_cmd.keys())
assert sorted(doe_cmd.keys()) == sorted(doe_sol.keys())

for resultfilename in doe_def:
row = doe_def[resultfilename]

assert resultfilename in doe_sol
sol = doe_sol[resultfilename]

var_dict = {
# simple / non-structural parameters
'a': float(row['a']),
'b': float(row['b']),
}

for var in var_dict:
assert var in sol['data']
assert np.isclose(sol['data'][var][-1], var_dict[var])
12 changes: 8 additions & 4 deletions tests/test_ModelicaSystemCmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ def model_firstorder(tmp_path):

@pytest.fixture
def mscmd_firstorder(model_firstorder):
mod = OMPython.ModelicaSystem()
mod = OMPython.ModelicaSystemOMC()
mod.model(
model_file=model_firstorder,
model_name="M",
)
mscmd = OMPython.ModelicaSystemCmd(
session=mod.get_session(),

mscmd = OMPython.ModelExecutionCmd(
runpath=mod.getWorkDirectory(),
modelname=mod._model_name,
cmd_local=mod.get_session().model_execution_local,
cmd_windows=mod.get_session().model_execution_windows,
cmd_prefix=mod.get_session().model_execution_prefix(cwd=mod.getWorkDirectory()),
model_name=mod._model_name,
)

return mscmd


Expand Down
Loading
Loading