Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2,104 changes: 1,283 additions & 821 deletions OMPython/ModelicaSystem.py

Large diffs are not rendered by default.

1,376 changes: 938 additions & 438 deletions OMPython/OMCSession.py

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions OMPython/OMTypedParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,6 @@ def om_parser_typed(string) -> Any:
if len(res) == 0:
return None
return res[0]


parseString = om_parser_typed
57 changes: 52 additions & 5 deletions OMPython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,90 @@
from OMPython.ModelicaSystem import (
LinearizationResult,
ModelicaSystem,
ModelicaSystemCmd,
ModelicaSystemOMC,
ModelExecutionCmd,
ModelicaSystemDoE,
ModelicaDoEOMC,
ModelicaSystemError,
ModelicaSystemRunner,
ModelicaDoERunner,

doe_get_solutions,

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

OMSessionRunner,

OMCSessionABC,

ModelExecutionData,
ModelExecutionException,

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

OMPathRunnerBash,
OMPathRunnerLocal,

OMCSessionWSL,
OMCSessionZMQ,

OMCProcessLocal,
OMCProcessPort,
OMCProcessDocker,
OMCProcessDockerContainer,
)

# global names imported if import 'from OMPython import *' is used
__all__ = [
'LinearizationResult',

'ModelExecutionData',
'ModelExecutionException',

'ModelicaSystem',
'ModelicaSystemOMC',
'ModelicaSystemCmd',
'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',

'OMCProcessLocal',
'OMCProcessPort',
'OMCProcessDocker',
'OMCProcessDockerContainer',
]
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])
Loading
Loading