Skip to content

Commit

Permalink
Rebased branch eis to main and merged stashed files
Browse files Browse the repository at this point in the history
  • Loading branch information
eisDNV committed Dec 20, 2024
1 parent ad2ccb0 commit 60d804b
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/sim_explorer/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ def do_actions(_t: float, _a, _iter, time: int, record: bool = True):
self.res.add(time / self.cases.timefac, a.args[0], a.args[1], a.args[2], a())

self.cases.simulator.reset()

if dump is not None:
self.res.save(dump)

Expand Down
2 changes: 2 additions & 0 deletions src/sim_explorer/json5.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ def _value(self):
elif isinstance(v, str) and not len(v): # might be empty due to trailing ','
return ""

if q2 >= 0: # explicitly quoted values are treated as strings!
return str(v)
try:
return int(v) # type: ignore
except Exception:
Expand Down
12 changes: 8 additions & 4 deletions src/sim_explorer/simulator_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ class SimulatorInterface:
description (str)="": Optional possibility to provide a system description
simulator (CosimExecution)=None: Optional possibility to insert an existing simulator object.
Otherwise this is generated through CosimExecution.from_osp_config_file().
log_level (CosimLogLevel): Per default the level is set to FATAL,
but it can be set to TRACE, DEBUG, INFO, WARNING, ERROR or FATAL (e.g. for debugging purposes)
log_level (str) = 'fatal': Per default the level is set to 'fatal',
but it can be set to 'trace', 'debug', 'info', 'warning', 'error' or 'fatal' (e.g. for debugging purposes)
fmus_available (bool) = False: Optional possibility to state that all FMUs shall be explicitly available,
and the interface object is thus able to attain all interface information from the modelDescription files.
The OSP interface has such information pre-loaded and the FMUs are thus not explicitly necessary.
"""

def __init__(
Expand All @@ -76,12 +79,13 @@ def __init__(
name: str | None = None,
description: str = "",
simulator: CosimExecution | None = None,
log_level: CosimLogLevel = CosimLogLevel.FATAL,
log_level: str = 'fatal',
fmus_available: bool = False,
):
self.name = name # overwrite if the system includes that
self.description = description # overwrite if the system includes that
self.sysconfig: Path | None = None
log_output_level(log_level)
log_output_level(CosimLogLevel[log_level.upper()])
self.simulator: CosimExecution
if simulator is None: # instantiate the simulator through the system config file
self.sysconfig = Path(system)
Expand Down
46 changes: 45 additions & 1 deletion src/sim_explorer/utils/osp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path

from sim_explorer.json5 import Json5
from component_model.utils.xml import read_xml


# ==========================================
Expand Down Expand Up @@ -179,7 +180,6 @@ def make_connection(main: str, sub1: str, attr1: dict, sub2: str, attr2: dict):
tree.write(file, encoding="utf-8")
return file


def osp_system_structure_from_js5(file: Path, dest: Path | None = None):
"""Make a OspSystemStructure file from a js5 specification.
The js5 specification is closely related to the make_osp_systemStructure() function (and uses it).
Expand All @@ -206,3 +206,47 @@ def osp_system_structure_from_js5(file: Path, dest: Path | None = None):
)

return ss

def read_system_structure_xml( file: Path):
"""Read the system structure in xml format and return as js5 dict, similar to ..._from_js5."""
def type_value( typ:str, value:str):
return {'Real': float, 'Integer': int, 'Boolean': bool, 'String': str}[typ]( value)
el = read_xml( file)
assert el.tag.endswith("OspSystemStructure"), f"<OspSystemStructure> expected. Found {el.tag}"
ns = el.tag.split("{")[1].split("}")[0]
bss = el.find(".//BaseStepSize") or 0.01
header = {
"xmlns" : ns,
"version" : el.get( "version", "'0.1'"),
"StartTime": el.find(".//StartTime") or 0.0,
"Algorithm": el.find(".//Algorithm") or 'fixedStep',
"BaseStepSize": bss,
}

simulators : dict = {}
for sim in el.findall(".//{*}Simulator"):
props = {
"source" : sim.get('source'),
"stepSize" : sim.get('stepSize', bss),
}
for initial in sim.findall(".//{*}InitialValue"):
props.update( { initial.get('variable') : type_value( initial[0].tag.split('}')[1], initial[0].get('value'))})
simulators.update( {sim.get('name') : props})

structure = {"header" : header, "Simulators" : simulators}
connections = {}
for c in ("Variable", "Signal", "Group", "SignalGroup"):
cons = []
for con in el.findall(".//{*}"+c+"Connection"):
assert len(con) == 2, f"Two sub-elements expected. Found {len(con)}"
props = []
for i in range(2):
for p in con[i].attrib.values():
props.append( p)
cons.append( props)
if len( cons):
connections.update( {"Connections"+c : cons})
if len(connections):
structure.update( connections)

return structure
Binary file modified tests/data/Oscillator/HarmonicOscillator.fmu
Binary file not shown.
16 changes: 0 additions & 16 deletions tests/data/crane_table.js5

This file was deleted.

0 comments on commit 60d804b

Please sign in to comment.