Skip to content
Merged
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
95 changes: 56 additions & 39 deletions OMPython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,55 @@ def setTempDirectory(self, customBuildDirectory):
def getWorkDirectory(self):
return self.tempdir

def _run_cmd(self, cmd: list, verbose: bool = True):
logger.debug("Run OM command {} in {}".format(cmd, self.tempdir))

if platform.system() == "Windows":
omhome = os.path.join(os.environ.get("OPENMODELICAHOME"))
dllPath = (os.path.join(omhome, "bin")
+ os.pathsep + os.path.join(omhome, "lib/omc")
+ os.pathsep + os.path.join(omhome, "lib/omc/cpp")
+ os.pathsep + os.path.join(omhome, "lib/omc/omsicpp"))

# include path to resources of defined external libraries
for element in self.lmodel:
if element is not None:
if isinstance(element, str):
if element.endswith("package.mo"):
pkgpath = element[:-10] + '/Resources/Library/'
for wver in ['win32', 'win64']:
pkgpath_wver = pkgpath + '/' + wver
if os.path.exists(pkgpath_wver):
dllPath = pkgpath_wver + os.pathsep + dllPath

# fix backslash in path definitions
dllPath = dllPath.replace("\\", "/")

my_env = os.environ.copy()
my_env["PATH"] = dllPath + os.pathsep + my_env["PATH"]
else:
# TODO: how to handle path to resources of external libraries for any system not Windows?
my_env = None

currentDir = os.getcwd()
try:
os.chdir(self.tempdir)
p = subprocess.Popen(cmd, env=my_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()

stdout = stdout.decode('ascii').strip()
stderr = stderr.decode('ascii').strip()
if stderr:
logger.warning("OM error: {}".format(stderr))
if verbose and stdout:
logger.info("OM output:\n{}".format(stdout))
p.wait()
p.terminate()
os.chdir(currentDir)
except Exception as e:
os.chdir(currentDir)
raise Exception("Error running command {}: {}".format(repr(cmd), e))

def buildModel(self, variableFilter=None, verbose=True):
if variableFilter is not None:
self.variableFilter = variableFilter
Expand Down Expand Up @@ -1280,32 +1329,15 @@ def simulate(self, resultfile=None, simflags=None, verbose=True): # 11
getExeFile = os.path.join(self.tempdir, '{}.{}'.format(self.modelName, "exe")).replace("\\", "/")
else:
getExeFile = os.path.join(self.tempdir, self.modelName).replace("\\", "/")
currentDir = os.getcwd()
if (os.path.exists(getExeFile)):

if os.path.exists(getExeFile):
cmd = getExeFile + override + csvinput + r + simflags
cmd = cmd.split(" ")
#print(cmd)
os.chdir(self.tempdir)
if (platform.system() == "Windows"):
omhome = os.path.join(os.environ.get("OPENMODELICAHOME"))
dllPath = os.path.join(omhome, "bin").replace("\\", "/") + os.pathsep + os.path.join(omhome, "lib/omc").replace("\\", "/") + os.pathsep + os.path.join(omhome, "lib/omc/cpp").replace("\\", "/") + os.pathsep + os.path.join(omhome, "lib/omc/omsicpp").replace("\\", "/")
my_env = os.environ.copy()
my_env["PATH"] = dllPath + os.pathsep + my_env["PATH"]
if not verbose:
p = subprocess.Popen(cmd, env=my_env, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
else:
p = subprocess.Popen(cmd, env=my_env)
else:
if not verbose:
p = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
else:
p = subprocess.Popen(cmd)
p.wait()
p.terminate()
os.chdir(currentDir)
self._run_cmd(cmd=cmd, verbose=verbose)

self.simulationFlag = True
else:
raise Exception("Error: Application file path not found: " + getExeFile)
raise Exception("Error: Application file path not found: " + getExeFile)

# to extract simulation results
def getSolutions(self, varList=None, resultfile=None): # 12
Expand Down Expand Up @@ -1741,23 +1773,11 @@ def linearize(self, lintime = None, simflags= None): # 22
if simflags is None:
simflags = ""

currentDir = os.getcwd()
if (os.path.exists(getExeFile)):
cmd = getExeFile + linruntime + override + csvinput + simflags
# print(cmd)
os.chdir(self.tempdir)
if (platform.system() == "Windows"):
omhome = os.path.join(os.environ.get("OPENMODELICAHOME"))
dllPath = os.path.join(omhome, "bin").replace("\\", "/") + os.pathsep + os.path.join(omhome, "lib/omc").replace("\\", "/") + os.pathsep + os.path.join(omhome, "lib/omc/cpp").replace("\\", "/") + os.pathsep + os.path.join(omhome, "lib/omc/omsicpp").replace("\\", "/")
my_env = os.environ.copy()
my_env["PATH"] = dllPath + os.pathsep + my_env["PATH"]
p = subprocess.Popen(cmd, env=my_env)
p.wait()
p.terminate()
else:
os.system(cmd)
cmd = cmd.split(' ')
self._run_cmd(cmd=cmd)
else:
os.chdir(currentDir)
raise Exception("Error: Application file path not found: " + getExeFile)

# code to get the matrix and linear inputs, outputs and states
Expand All @@ -1780,13 +1800,10 @@ def linearize(self, lintime = None, simflags= None): # 22
self.linearoutputs = outputVars
self.linearstates = stateVars
return [A, B, C, D]
os.chdir(currentDir)
except:
os.chdir(currentDir)
raise Exception("ModuleNotFoundError: No module named 'linearized_model'")
else:
errormsg = self.getconn.sendExpression("getErrorString()")
os.chdir(currentDir)
return print("Linearization failed: ", "\"" , linearFile,"\"" ," not found \n", errormsg)


Expand Down
38 changes: 38 additions & 0 deletions tests/test_linearization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import OMPython
import tempfile, shutil, os
import pytest

class Test_Linearization:
def loadModel(self):
self.tmp = tempfile.mkdtemp(prefix='tmpOMPython.tests')
with open("%s/linearTest.mo" % self.tmp, "w") as fout:
fout.write("""
model linearTest
Real x1(start=1);
Real x2(start=-2);
Real x3(start=3);
Real x4(start=-5);
parameter Real a=3,b=2,c=5,d=7,e=1,f=4;
equation
a*x1 = b*x2 -der(x1);
der(x2) + c*x3 + d*x1 = x4;
f*x4 - e*x3 - der(x3) = x1;
der(x4) = x1 + x2 + der(x3) + x4;
end linearTest;
""")

def __del__(self):
shutil.rmtree(self.tmp, ignore_errors=True)

def test_example(self):
self.loadModel()
filePath = os.path.join(self.tmp,"linearTest.mo").replace("\\", "/")
print(filePath)
mod = OMPython.ModelicaSystem(filePath, "linearTest")
[A, B, C, D] = mod.linearize()
expected_matrixA = [[-3, 2, 0, 0], [-7, 0, -5, 1], [-1, 0, -1, 4], [0, 1, -1, 5]]
assert A == expected_matrixA, f"Matrix does not match the expected value. Got: {A}, Expected: {expected_matrixA}"
assert B == [], f"Matrix does not match the expected value. Got: {B}, Expected: {[]}"
assert C == [], f"Matrix does not match the expected value. Got: {C}, Expected: {[]}"
assert D == [], f"Matrix does not match the expected value. Got: {D}, Expected: {[]}"