Metadata-Version: 2.4
Name: syssimx
Version: 0.1.5
Summary: A Python framework for heterogeneous system co-simulation (Modelica FMUs, OpenSim, FEM).
Author-email: Florian Frech <florianfrech@outlook.de>
License-Expression: MIT
Project-URL: Homepage, https://github.com/FlorianFrech/SystemSimulation
Project-URL: Documentation, https://syssimx.readthedocs.io/en/latest/
Project-URL: Repository, https://github.com/FlorianFrech/SystemSimulation
Project-URL: Issues, https://github.com/FlorianFrech/SystemSimulation/issues
Keywords: simulation,co-simulation,FMU,FEM,OpenSim,Modelica
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
License-File: THIRD_PARTY_LICENSES.MD
License-File: LICENSES/Apache-2.0.txt
License-File: LICENSES/CC-BY-4.0.txt
Requires-Dist: numpy
Requires-Dist: scipy
Requires-Dist: pint
Requires-Dist: networkx
Requires-Dist: pandas
Requires-Dist: matplotlib
Requires-Dist: ipywidgets
Requires-Dist: traitlets
Requires-Dist: graphviz
Requires-Dist: pydot
Provides-Extra: fmu
Requires-Dist: fmpy; extra == "fmu"
Requires-Dist: OMPython; extra == "fmu"
Provides-Extra: fem
Requires-Dist: ngsolve; extra == "fem"
Requires-Dist: webgui_jupyter_widgets; extra == "fem"
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: mypy>=1.5.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: ipython>=8.12.0; extra == "dev"
Requires-Dist: ipykernel>=6.25.0; extra == "dev"
Requires-Dist: jupyter>=1.0.0; extra == "dev"
Requires-Dist: jupyterlab>=4.0.0; extra == "dev"
Requires-Dist: sphinx>=7.0.0; extra == "dev"
Requires-Dist: sphinx-autodoc-typehints>=2.0.0; extra == "dev"
Requires-Dist: sphinx-book-theme>=1.1.0; extra == "dev"
Requires-Dist: myst-nb>=1.1.0; extra == "dev"
Provides-Extra: all
Requires-Dist: syssimx[fem,fmu,viz]; extra == "all"
Provides-Extra: full
Requires-Dist: syssimx[all,dev]; extra == "full"
Dynamic: license-file

# SysSimX

**SysSimX** is a free and open-source Python library for system simulation.
It allows you to build hybrid and heterogenous system models by connecting system component models from different environments, including:
- **FMU Components** - [Functional Mock-up Units (FMI 2.0 Co-Simulation)](https://fmi-standard.org/)
- **OpenSim Components** - Musculoskeletal biomechanics models using [OpenSim](https://opensim.stanford.edu/)
- **FEM Components** - Finite Element Models using [NGSolve](https://ngsolve.org/)
- **Custom Python Components** - User-defined models implemented directly in Python

The library comes with a [user documentation site]() that includes installation instructions, core concepts, API references, and tutorials covering fundamental techniques, tool integrations, and a case study.

## Key Features

- **Graph-Based Execution:** Automatic dependency analysis with direct feedthrough and algebraic loop detection. Components are executed in topologically sorted order.

- **Algebraic Loop Handling:** Detection and iterative solving using the Interface Jacobian-based Co-Simulation Algorithm (IJCSA).

- **Hybrid Co-Simulation:** Event detection via zero-crossing indicators with bisection-based time localization and superdense time semantics.

- **Multiple Master Algorithms:** Choose from Jacobi (parallel), Gauss-Seidel (sequential), or Hybrid (event-driven) algorithms.

- **Multi-Tool Integration:** Seamlessly connect FMUs, OpenSim models, and NGSolve FEM models in a single system.

- **Multi-Model Switching:** Dynamically switch between multiple models of the same component during simulation.

- **Unit-Aware Connections:** Automatic unit conversion between ports using Pint.

- **Extensible Component API:** Base class for custom components with lifecycle methods for initialization, stepping, and output updates.

## Installation

The `syssimx` package is available on [PyPI](https://pypi.org/project/syssimx/). You can install it using `pip`. Optional extras are available for FMU, OpenSim, and FEM support.

### Basic install

```bash
pip install syssimx
```

### Optional extras

```bash
pip install "syssimx[fmu]"
pip install "syssimx[fem]"
pip install "syssimx[dev]"
pip install "syssimx[all]"
pip install "syssimx[full]"
```

### OpenSim note (important)

OpenSim is conda-only and ABI-coupled to specific NumPy/SciPy builds. Recommended order:

1. Install `syssimx` with `pip`.
2. Install OpenSim with `conda` using ABI-compatible NumPy/SciPy pins.

See the full installation guide:
- `docs/01_getting_started/01_installation.ipynb`

## Quickstart Example

The example below creates a simple linear source feeding an integrator.

```python
import matplotlib.pyplot as plt

from syssimx import CoSimComponent, Connection, System
from syssimx.core import PortSpec, PortType


class LinearSource(CoSimComponent):
    def __init__(self, name: str, a: float = 1.0, b: float = 0.0):
        super().__init__(name, group="Source")
        self.a = a
        self.b = b
        self.output_specs.update({
            "y": PortSpec(name="y", type=PortType.REAL, direction="out")
        })

    def _initialize_component(self, t0: float) -> None:
        pass

    def _do_step_internal(self, t: float, dt: float) -> None:
        pass

    def _update_output_states(self, t: float | None = None, event_names=None):
        t_now = 0.0 if t is None else t
        self.outputs["y"].set(self.a * t_now + self.b, t)


class Integrator(CoSimComponent):
    def __init__(self, name: str, x0: float = 0.0):
        super().__init__(name, group="Integrator")
        self.x0 = x0
        self.input_specs.update({
            "u": PortSpec(name="u", type=PortType.REAL, direction="in")
        })
        self.output_specs.update({
            "y": PortSpec(name="y", type=PortType.REAL, direction="out")
        })

    def _initialize_component(self, t0: float) -> None:
        self.x = self.x0
        self.outputs["y"].set(self.x, t0)

    def _do_step_internal(self, t: float, dt: float) -> None:
        u = self.inputs["u"].get()
        self.x = self.x + dt * float(u)

    def _update_output_states(self, t: float | None = None, event_names=None):
        self.outputs["y"].set(self.x, t)


source = LinearSource(name="LinearSource", a=1.0, b=0.0)
integrator = Integrator(name="Integrator", x0=0.0)

system = System(name="QuickstartSystem")
system.add_component(source)
system.add_component(integrator)
system.add_connection(Connection(
    src_comp="LinearSource", src_port="y",
    dst_comp="Integrator", dst_port="u",
))

system.initialize(t0=0.0)
system.run(t0=0.0, tf=5.0, dt=0.1)

history = system.get_history()
t_vals, data = history["Integrator"]
y_vals = data["y"]

plt.plot(t_vals, y_vals)
plt.xlabel("Time (s)")
plt.ylabel("Integrator output")
plt.title("SysSimX Quickstart")
plt.grid(True)
plt.show()
```

For the complete walkthrough, see:
- `docs/01_getting_started/02_quickstart.ipynb`

## Documentation

- Documentation entry: `docs/index.rst`
- Installation guide: `docs/01_getting_started/01_installation.ipynb`
- Core concepts: `docs/01_getting_started/03_concepts.ipynb`
- Quickstart tutorial: `docs/01_getting_started/02_quickstart.ipynb`
- API docs: `docs/02_api/`
- Tutorials and case studies:
  - `docs/03_core_tutorials/`
  - `docs/04_tool_integration/`
  - `docs/05_case_study/`

## Project Status

SysSimX is under active development. APIs and behavior may evolve as algorithms and component integrations are extended.

## License

- Project license: MIT (`LICENSE`)
- Third-party dependencies and attributions: `THIRD_PARTY_LICENSES.MD`
