2

I am starting to use Python to run my Dymola models since I think that it has more potential than the Dymola scripts “.mos”. I’ve already set a similar code than the “DymolaExample.py”.

from dymola.dymola_interface import DymolaInterface
import os

# Instantiate the Dymola interface and start Dymola
dymola = DymolaInterface()

# Call a function in Dymola and check its return value
result = dymola.simulateModel(
    "Modelica.Mechanics.Rotational.Examples.CoupledClutches",
    resultFile=r"N:\SOLAR\3.PROYECTOS\3.4 OTROS\GRUPO HIBRIDO CSP-FV\InterfacePythonDymola\python_interface\examples\nf")
if not result:
    print("Simulation failed. Below is the translation log.")
    log = dymola.getLastErrorLog()
    print(log)
    exit(1)

# dymola.plot(["J1.w", "J2.w", "J3.w", "J4.w"])
# plotPath = os.getcwd() + "/plot.png"
# dymola.ExportPlotAsImage(plotPath)

However, I am running models to evaluate the annual performance of a system with high computational cost. Is it possible to see the Dymola results while the code is running? Or at least see what is the Simulating Time in “real-time” from Python to see if the simulation is going to take much more time?

AnHeuermann
  • 761
  • 3
  • 14
  • This is not perfect if you want to process the simulating time in your code, but if you only need to have a way to check manually you can open Dymola with `dymola = DymolaInterface(showwindow=True)` . Then the GUI opens on your machine and you can easily plot e.g. the CPU time to get an idea about progress while the Python code continues to run. – marcu1000s Mar 17 '23 at 08:08

1 Answers1

2

Dymola periodically writes the current values of a running simulation to the result file. To achieve your goal, you can read the result file and check for the last value of the time variable. To do so, we have to run our simulation asynchronously, e.g. in a thread (see Asynchronous method call in Python? for more solutions).

While the thread is alive, we read the result file. This can not be done easily with the dymola python interface, but the SDF package makes this a trivial task. To make sure that we don't try to access the result file before the simulation is started, the model is explicitly translated first and only the actual simulation runs in the thread.

import os
import time
import threading
from pathlib import Path

import sdf
from dymola.dymola_interface import DymolaInterface


def sim():
    """Simulate model in Dymola."""
    ok = dymola.simulateModel(model, stopTime=stop_time,
                              resultFile=result_file.with_suffix('').as_posix())
    if ok:
        print("done.")
    else:
        print("simulation failed.")


def get_time():
    """Check current simulation time."""
    time = sdf.load(result_file.as_posix(), '/Time')
    print(f"time: {time.data[-1]:.1f}")


def create_slow_model():
    """Create new package with model that runs approximately in realtime."""
    dymola.setClassText("", """package MyPackage
end MyPackage;""")
    dymola.setClassText("MyPackage", """model SlowSim
  Modelica_DeviceDrivers.ClockedBlocks.OperatingSystem.SynchronizeRealtime synchronizeRealtime;
end SlowSim;""")


# user setup
model = "MyPackage.SlowSim"
stop_time = 10
check_interval = 1   # in seconds

cwd = Path(os.getcwd())
result_file = cwd / f"{model.split('.')[-1]}.mat"

# init
dymola = DymolaInterface()
create_slow_model()

# translate
dymola.translateModel(model)

# simulate
thr = threading.Thread(target=sim)
thr.start()
while thr.is_alive():
    get_time()
    time.sleep(check_interval)

marco
  • 5,944
  • 10
  • 22