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
2 changes: 1 addition & 1 deletion include/OMSimulator/OMSimulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ OMSAPI oms_status_enu_t OMSCALL oms_getResultFile(const char* cref, char** filen
OMSAPI oms_status_enu_t OMSCALL oms_getSolver(const char* cref, oms_solver_enu_t* solver);
OMSAPI oms_status_enu_t OMSCALL oms_getStartTime(const char* cref, double* startTime);
OMSAPI oms_status_enu_t OMSCALL oms_getState(const char* cref);
OMSAPI oms_status_enu_t OMSCALL oms_getResultFileSignals(const char* filename, const char** signals);
OMSAPI oms_status_enu_t OMSCALL oms_getResultFileSignals(const char* filename, const char** signalNames);
OMSAPI oms_status_enu_t OMSCALL oms_getStopTime(const char* cref, double* stopTime);
OMSAPI oms_status_enu_t OMSCALL oms_getString(const char* cref, char** value);
OMSAPI oms_status_enu_t OMSCALL oms_getSubModelPath(const char* cref, char** path);
Expand Down
10 changes: 5 additions & 5 deletions src/OMSimulatorLib/OMSimulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,21 +152,21 @@ int oms_compareSimulationResults(const char* filenameA, const char* filenameB, c
return rc ? 1 : 0;
}

oms_status_enu_t oms_getResultFileSignals(const char* filename, const char ** signals)
oms_status_enu_t oms_getResultFileSignals(const char* filename, const char ** signalNames)
{
oms::ResultReader* reader = oms::ResultReader::newReader(filename);
std::string result; // build string in-place
for (const auto &signal : reader->getAllSignals())
for (const auto &signalName : reader->getAllSignals())
{
if (!result.empty())
result.append(","); // append comma
result.append(signal); // append signal name
result.append(signalName); // append signal name
}

delete reader;

*signals = oms::mallocAndCopyString(result);
if (!*signals)
*signalNames = oms::mallocAndCopyString(result);
if (!*signalNames)
return oms_status_fatal;
return oms_status_ok;
}
Expand Down
7 changes: 7 additions & 0 deletions src/OMSimulatorPython/capi.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ def __init__(self):
self.obj.oms_setStopTime.restype = ctypes.c_int
self.obj.oms_setTolerance.argtypes = [ctypes.c_char_p, ctypes.c_double]
self.obj.oms_setTolerance.restype = ctypes.c_int
self.obj.oms_setFixedStepSize.argtypes = [ctypes.c_char_p, ctypes.c_double]
self.obj.oms_setFixedStepSize.restype = ctypes.c_int
self.obj.oms_setVariableStepSize.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double]
self.obj.oms_setVariableStepSize.restype = ctypes.c_int
self.obj.oms_setLogFile.argtypes = [ctypes.c_char_p]
Expand Down Expand Up @@ -240,6 +242,11 @@ def setTolerance(self, cref, relativeTolerance) -> Status:
status = self.obj.oms_setTolerance(cref.encode(), relativeTolerance)
return Status(status)

def setFixedStepSize(self, cref, stepSize) -> Status:
'''Set the variable step size parameters for the simulation.'''
status = self.obj.oms_setFixedStepSize(cref.encode(), stepSize)
return Status(status)

def setVariableStepSize(self, cref, initialStepSize, minStepSize, maxStepSize) -> Status:
'''Set the variable step size parameters for the simulation.'''
status = self.obj.oms_setVariableStepSize(cref.encode(), initialStepSize, minStepSize, maxStepSize)
Expand Down
12 changes: 10 additions & 2 deletions src/OMSimulatorPython/instantiated_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,19 @@ def setTolerance(self, tolerance: float):
if status != Status.ok:
raise RuntimeError(f"Failed to set tolerance: {status}")

def setStepSize(self, stepSize: float):
def setFixedStepSize(self, stepSize: float):
if self.fmuInstantitated is False:
raise RuntimeError("FMU must be instantiated before setting variable step size")

status = Capi.setVariableStepSize(self.modelName, 1e-6, 1e-12, stepSize)
status = Capi.setFixedStepSize(self.modelName, stepSize)
if status != Status.ok:
raise RuntimeError(f"Failed to set fixed step size: {status}")

def setVariableStepSize(self, initialStepSize: float, minimumStepSize: float, maximumStepSize: float):
if self.fmuInstantitated is False:
raise RuntimeError("FMU must be instantiated before setting variable step size")

status = Capi.setVariableStepSize(self.modelName, initialStepSize, minimumStepSize, maximumStepSize)
if status != Status.ok:
raise RuntimeError(f"Failed to set variable step size: {status}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
## simulation settings
instantiated_model.setStopTime(1.0)
instantiated_model.setTolerance(1e-6)
instantiated_model.setStepSize(1e-4)
instantiated_model.setFixedStepSize(1e-4)

instantiated_model.initialize()
instantiated_model.simulate()
Expand Down
2 changes: 1 addition & 1 deletion testsuite/AircraftVehicleDemonstrator/embrace1.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
## simulation settings
instantiated_model.setResultFile("embrace1_res.mat")
instantiated_model.setStopTime(12.0)
instantiated_model.setStepSize(1e-3)
instantiated_model.setFixedStepSize(1e-3)
instantiated_model.setLoggingInterval(1)

instantiated_model.initialize()
Expand Down
2 changes: 1 addition & 1 deletion testsuite/AircraftVehicleDemonstrator/embrace2.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
## simulation settings
instantiated_model.setResultFile("embrace2_res.mat")
instantiated_model.setStopTime(12.0)
instantiated_model.setStepSize(1e-3)
instantiated_model.setFixedStepSize(1e-3)
instantiated_model.setLoggingInterval(1)

instantiated_model.initialize()
Expand Down
62 changes: 62 additions & 0 deletions testsuite/simulation/DualMassOscillator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
## status: correct
## teardown_command: rm -rf DualMassOscillator.ssp DualMassOscillator_res.mat
## linux: yes
## ucrt64: yes
## win: yes
## mac: yes

from OMSimulator import SSP, CRef, Settings

Settings.suppressPath = True


model = SSP()
model.addResource('../resources/DualMassOscillator.System1.fmu', new_name='resources/system1.fmu')
model.addResource('../resources/DualMassOscillator.System2.fmu', new_name='resources/system2.fmu')


model.addComponent(CRef('default', 'system1'), 'resources/system1.fmu')
model.addComponent(CRef('default', 'system2'), 'resources/system2.fmu')

## add connection
model.addConnection(CRef('default', 'system1', 'F'), CRef('default', 'system2', 'F'))
model.addConnection(CRef('default', 'system1', 'x1'), CRef('default', 'system2', 'x1'))
model.addConnection(CRef('default', 'system1', 'v1'), CRef('default', 'system2', 'v1'))
model.addConnection(CRef('default', 'system1', 'a1'), CRef('default', 'system2', 'a1'))

model.export('DualMassOscillator.ssp')

model2 = SSP('DualMassOscillator.ssp')

instantiated_model = model2.instantiate() ## internally generate the json file and also set the model state like virgin,
instantiated_model.setResultFile("DualMassOscillator_res.mat")
instantiated_model.setStopTime(10)

instantiated_model.setFixedStepSize(1e-4)

## set value
instantiated_model.setValue(CRef('default', 'system1', 'x1_start'), 0.0)
instantiated_model.setValue(CRef('default', 'system2', 'x2_start'), 0.5)

instantiated_model.initialize()
print(f"info: Initialization")
print(f"info: default.system1.x1: {instantiated_model.getValue(CRef('default', 'system1', 'x1'))}")
print(f"info: default.system2.x2: {instantiated_model.getValue(CRef('default', 'system2', 'x2'))}")

instantiated_model.simulate()
print(f"info: Simulation")
print(f"info: default.system1.x1: {instantiated_model.getValue(CRef('default', 'system1', 'x1'))}")
print(f"info: default.system2.x2: {instantiated_model.getValue(CRef('default', 'system2', 'x2'))}")

instantiated_model.terminate()
instantiated_model.delete()

## Result:
## info: Result file: DualMassOscillator_res.mat (bufferSize=1)
## info: Initialization
## info: default.system1.x1: 0.0
## info: default.system2.x2: 0.5
## info: Simulation
## info: default.system1.x1: 0.051412690223479836
## info: default.system2.x2: 0.031858470461315964
## endResult
1 change: 1 addition & 0 deletions testsuite/simulation/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
TEST = ../rtest -v

TESTFILES = \
DualMassOscillator.py \
exportJson1.py \
exportJson2.py \
exportJson4.py \
Expand Down
2 changes: 1 addition & 1 deletion testsuite/simulation/PIController.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
instantiated_model = model2.instantiate() ## internally generate the json file and also set the model state like virgin,
instantiated_model.setStartTime(0.0)
instantiated_model.setStopTime(4.0)
instantiated_model.setStepSize(1e-3)
instantiated_model.setFixedStepSize(1e-3)
instantiated_model.setResultFile("PI_Controller.mat")

# set parameters
Expand Down
4 changes: 2 additions & 2 deletions testsuite/simulation/SimpleSimulation2.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## status: correct
## teardown_command: rm -rf SimpleSimulation1.ssp SimpleSimulation2_res.mat
## teardown_command: rm -rf SimpleSimulation2.ssp SimpleSimulation2_res.mat
## linux: yes
## ucrt64: yes
## win: yes
Expand Down Expand Up @@ -66,7 +66,7 @@
## |-- |-- |-- |-- Gain1.y -> Add1.u1
## |-- UnitDefinitions:
## |-- |-- Unit: 1
## |-- |-- |-- BaseUnit:
## |-- |-- |-- BaseUnit:
## |-- DefaultExperiment
## |-- |-- startTime: 0.0
## |-- |-- stopTime: 1.0
Expand Down