Co-Simulation Components#
FMU Component#
FMI 2.0 Co-Simulation FMU wrapper.
This module exposes FMUComponent, a CoSimComponent
implementation backed by an FMI 2.0 co-simulation FMU via fmpy. The component
derives input/output ports from the FMU model description, handles units for REAL
signals, applies parameter starts during initialization, and supports direct
feedthrough evaluation.
- class syssimx.components.fmu.FMUComponent[source]#
Bases:
CoSimComponentFMU co-simulation wrapper implementing the CoSimComponent interface.
Supports FMI 2.0 co-simulation FMUs, typed input/output ports (REAL, INT, BOOL, STRING), and unit-aware REAL ports via
pint.- __init__(name, fmu_path, group=None)[source]#
Create the FMU component and derive port specifications.
- Parameters:
- Raises:
RuntimeError – If the FMU is not a co-simulation FMU.
NotImplementedError – If the FMU uses an unsupported FMI version.
- _md: ModelDescription#
- _build_port_specs()[source]#
Build input/output PortSpec objects from the model description.
- Return type:
None
- _build_value_reference_map()[source]#
Cache value references for fast typed access.
- Return type:
None
- _analyze_model_structure()[source]#
Populate model structure dependencies for outputs/derivatives/initials.
- Return type:
None
- _initialize_component(t0)[source]#
Initialize and instantiate the FMU for simulation.
Extracts the FMU archive.
Creates the FMU2Slave instance.
Sets up the experiment with the start time.
Enters initialization mode.
Applies parameter start values.
Applies input start values from PortStates.
Exits initialization mode.
- Parameters:
t0 (float) – Simulation start time.
- Return type:
None
- reinitialize_instance(t0)[source]#
Recreate the FMU instance and enter initialized state at
t0.This is intentionally different from FMI
reset(). Some FMUs do not support reliable rollback throughfmi2Resetafter stepping, but can be restored by creating a fresh instance and applying reconstructed initial conditions through parameters.- Parameters:
t0 (float)
- Return type:
None
- _apply_parameters_starts()[source]#
Apply parameter start values to the FMU instance.
- Return type:
None
- _apply_input_starts()[source]#
Push initial input values from PortStates into the FMU.
- Return type:
None
- _abc_impl = <_abc._abc_data object>#
- set_inputs(signals, t=None)[source]#
Set input port values and push them to the FMU.
- Parameters:
- Raises:
KeyError – If an input name is unknown.
TypeError – If a value type does not match the port type.
ValueError – If a REAL input is missing a value after unit conversion.
- Return type:
None
- _update_output_states(t=None, event_names=None)[source]#
Refresh output PortStates from the FMU instance.
- get_state()[source]#
Return FMU variables as a serialized dictionary.
The dictionary includes variables that are not fixed and not local, along with their units and current values pulled from the FMU instance.
- evaluate_outputs(inputs, t=None)[source]#
Evaluate outputs for a given input set without advancing time.
- reset()[source]#
Reset the component and release the FMU instance.
After reset, the component can be reinitialized via
initialize().- Return type:
None
- soft_reset(t0=0.0)[source]#
Reset the FMU to initial state without releasing the instance.
Uses FMI
reset()to return to the instantiated state, then reinitializes with parameter and input starts.- Parameters:
t0 (float) – New start time for the simulation.
- Return type:
None
- syssimx.components.fmu._port_type_from_var(var)[source]#
Determine PortType from ScalarVariable type.
- Parameters:
var (ScalarVariable) – The model variable to determine the port type for.
- Returns:
The corresponding PortType.
- Return type:
- Raises:
NotImplementedError – If the variable type is unsupported.
FEM Component#
NGSolve transient structural-mechanics co-simulation wrapper.
FEMComponent is the concrete FEM backend for SysSimX. It wraps an NGSolve
finite-element model that is advanced in time with a constant-average-acceleration
(trapezoidal) Newmark scheme and exposes it through the CoSimComponent
interface. The class owns the parts that are common to any transient structural
NGSolve model:
the Newmark state grid functions
(u, v, a)and their previous-step buffers(u_old, v_old, a_old)and the velocity/acceleration update,snapshot / restore of that state for hybrid event localization and rollback,
multidim grid-function history recording (gated by
_record_history),resetof the Newmark state,a micro-stepped
do_steploop built from overridable hooks.
A concrete model (e.g. the controlled FEM pendulum) subclasses this and supplies the mesh, finite-element spaces, the variational form, and the physics-specific hooks. The base is deliberately backend-specific (NGSolve) and problem-specific (transient structural dynamics); a non-transient NGSolve model can override the step hooks to opt out of the Newmark update.
Requires the ngsolve optional dependency (pip install syssimx[fem]).
- class syssimx.components.fem.FEMComponent[source]#
Bases:
CoSimComponentConcrete NGSolve transient structural-mechanics component.
Subclasses implement
_initialize_component()(build mesh, spaces, forms, initial state) and_solve_step()(the nonlinear solve of one sub-step), and may override the optional step hooks below.- __init__(name, label=None, group=None)[source]#
Initialize a new co-simulation component.
- Parameters:
name (str) – Unique identifier for this component. Must be unique within the containing System. Used for connection definitions and graph construction.
label (str | None) – Human-readable display name for visualization and logging. Defaults to
nameif not provided.group (str | None) – Optional category for grouping related components (e.g., ‘sensors’, ‘actuators’, ‘controllers’). Used for filtering and organization in large systems.
Example
>>> comp = MyComponent("pid_1", label="PID Controller", group="controllers") >>> comp.name 'pid_1' >>> comp.label 'PID Controller'
- _init_newmark_state(fes)[source]#
Allocate the six Newmark state grid functions over
fes.- Parameters:
fes (Any)
- Return type:
None
- _shift_newmark_state()[source]#
Copy the current state into the previous-step buffers.
- Return type:
None
- _advance_newmark()[source]#
Update velocity and acceleration from the freshly solved displacement.
- Constant-average-acceleration (trapezoidal) Newmark update:
v = 2/τ (u - u_old) - v_old a = 2/τ (v - v_old) - a_old
- Return type:
None
- _register_history_field(history_attr, source_vec_fn)[source]#
Register a history grid function to receive a frame each sub-step.
- _record_history_frame()[source]#
Append one frame to every registered history field.
Skipped when
_record_historyis False (e.g. during hybrid trial steps) so the history reflects accepted simulation time only.- Return type:
None
- do_step(t, dt)[source]#
Advance from
ttot + dtvia internal micro-stepping.Overrides the single-shot
CoSimComponent.do_step: outputs and history are updated within each accepted sub-step so that recorded results and internal event hints are sub-step accurate.
- _do_step_internal(t, dt)[source]#
Subclass hook for time step computation.
Override this method to implement the component’s simulation logic. This is where state integration, solver calls, and internal computations happen.
- Parameters:
- Return type:
None
Example
Simple Euler integration:
def _do_step_internal(self, t: float, dt: float) -> None: u = self.inputs['u'].get() self._state += self._derivative(self._state, u) * dt
Note
Do NOT update
self.there;do_step()handles thatDo NOT call
_update_output_states(); done bydo_step()For event detection, call
report_internal_event()if micro-stepping detects a zero-crossing
See also
do_step(): Public interface that calls this methodreport_internal_event(): Report events from micro-stepping
- _pre_solve(t_current, effective_dt)[source]#
Hook before the nonlinear solve (e.g. contact update, adaptive τ).
- abstractmethod _solve_step()[source]#
Solve the nonlinear variational form for the current sub-step.
- Return type:
None
- _post_solve(t_current)[source]#
Hook after the Newmark update (e.g. event detection, stress fields).
- Parameters:
t_current (float)
- Return type:
None
- _after_substep(t_current)[source]#
Hook after outputs are recorded (e.g. redraw, monitoring update).
- Parameters:
t_current (float)
- Return type:
None
- load_mesh_from_file(path)[source]#
Optional: load a mesh from file (GMSH, VTK, XDMF, …).
- Parameters:
path (Path)
- Return type:
None
- _abc_impl = <_abc._abc_data object>#
OpenSim Component#
- class syssimx.components.opensim.OpenSimComponent[source]#
Bases:
CoSimComponentWrapper around an OpenSim model to implement the CoSimComponent interface.
- model: opensim.Model#
- state: opensim.State#
- manager: opensim.Manager#
- _finalize_model(t0)[source]#
Complete OpenSim initialization after model is built/loaded. Call this at the end of subclass _initialize_component().
- Parameters:
t0 (float)
- Return type:
None
- reset()[source]#
Reset the component to a clean state before (before initialization).
- Return type:
None
- get_coordinate_value(coord_name)[source]#
Get current value of named coordinate (generalized position).
- get_coordinate_speed(coord_name)[source]#
Get current speed of named coordinate (generalized velocity).
- _abc_impl = <_abc._abc_data object>#