{"id":51619141,"url":"https://github.com/pathsim/fastsim","last_synced_at":"2026-07-12T18:00:25.405Z","repository":{"id":369260905,"uuid":"1201340316","full_name":"pathsim/fastsim","owner":"pathsim","description":"Rust reimplementation of PathSim with an identical Python API","archived":false,"fork":false,"pushed_at":"2026-07-11T12:52:56.000Z","size":30649,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-11T14:13:20.560Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://fast.pathsim.org/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pathsim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-04T14:47:15.000Z","updated_at":"2026-07-11T12:47:26.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pathsim/fastsim","commit_stats":null,"previous_names":["pathsim/fastsim"],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/pathsim/fastsim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pathsim%2Ffastsim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pathsim%2Ffastsim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pathsim%2Ffastsim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pathsim%2Ffastsim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pathsim","download_url":"https://codeload.github.com/pathsim/fastsim/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pathsim%2Ffastsim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35398566,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-12T18:00:19.470Z","updated_at":"2026-07-12T18:00:25.358Z","avatar_url":"https://github.com/pathsim.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"doc/logo.png\" width=\"350\" alt=\"FastSim Logo\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eA Rust block-diagram simulation engine\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Drop-in replacement for \u003ca href=\"https://github.com/pathsim/pathsim\"\u003ePathSim\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nFastSim is a Rust reimplementation of [PathSim](https://github.com/pathsim/pathsim) with an identical Python API via PyO3. Python callbacks are automatically traced into an optimized SSA graph, differentiated symbolically, and evaluated in Rust.\n\n## Features\n\n- **Drop-in compatible**: same API as PathSim; swap the import\n- **Rust engine**: zero-copy data paths, flat DAG evaluation, dynamic block sizing\n- **21 ODE solvers**: explicit and implicit, adaptive and fixed-step\n- **Standalone solvers**: `RKDP54.integrate(func, x0, time_end=50)` with automatic JIT compilation\n- **JIT compiler**: Python functions traced into flat-tape IR with CSE, constant folding, strength reduction, and FMA detection\n- **SIL verification**: `sim.verify_c()` compiles the generated C locally and pins it against the reference engine, sample by sample\n- **Automatic differentiation**: symbolic forward-mode AD for analytical Jacobians\n- **Standalone JIT + AD API**: `jit(func)` and `jacobian(func)` as JAX-style transformations\n- **Event handling**: zero-crossing detection, scheduled events, conditions for hybrid systems\n- **Hierarchical**: nest subsystems for modular designs\n- **Mutable parameters**: change block parameters at runtime with automatic reconstruction\n- **Dynamic ports**: blocks adapt their state dimension to connected inputs\n\n## Quick Example\n\n```python\nfrom fastsim import Simulation, Connection\nfrom fastsim.blocks import Integrator, Amplifier, Adder, Scope\n\n# Damped harmonic oscillator: x'' + 0.5x' + 2x = 0\nint_v = Integrator(5)       # velocity, v0=5\nint_x = Integrator(2)       # position, x0=2\namp_c = Amplifier(-0.5)     # damping\namp_k = Amplifier(-2)       # spring\nadd = Adder()\nscp = Scope()\n\nsim = Simulation(\n    blocks=[int_v, int_x, amp_c, amp_k, add, scp],\n    connections=[\n        Connection(int_v, int_x, amp_c),\n        Connection(int_x, amp_k, scp),\n        Connection(amp_c, add),\n        Connection(amp_k, add[1]),\n        Connection(add, int_v),\n    ],\n)\n\nsim.run(30)\ntime, [x] = scp.read()\n```\n\n## Standalone ODE Solvers\n\nAll 21 solvers are available as standalone integrators with automatic JIT compilation of the right-hand side and symbolic Jacobian generation for implicit solvers.\n\n```python\nfrom fastsim.solvers import RKDP54, ESDIRK43\n\ndef lorenz(x, t):\n    sigma, rho, beta = 10.0, 28.0, 8.0/3.0\n    return [sigma*(x[1]-x[0]), x[0]*(rho-x[2])-x[1], x[0]*x[1]-beta*x[2]]\n\n# Explicit adaptive solver\nt, x = RKDP54.integrate(lorenz, [1, 1, 1], time_end=50.0)\n\n# Implicit solver for stiff systems (Jacobian generated automatically via AD)\nt, x = ESDIRK43.integrate(robertson, [1, 0, 0], time_end=1.0, tolerance_lte_abs=1e-8)\n```\n\n## JIT Compilation and Automatic Differentiation\n\nPython functions are automatically traced into an optimized SSA computation graph and evaluated in Rust. Available as standalone transformations (JAX-style):\n\n```python\nfrom fastsim.jit import jit, jacobian\n\n# JIT compile (lazy tracing on first call)\nf = jit(lorenz)\nresult = f([1.0, 1.0, 1.0], 0.0)\n\n# Eager compilation with known input size\nf = jit(lorenz, n_x=3)\n\n# Automatic Jacobian via symbolic AD\njac_fn = jacobian(lorenz)\nJ = jac_fn([1.0, 1.0, 1.0], 0.0)  # 3x3 numpy array\n```\n\nSupported operations: arithmetic, `np.sin/cos/tan/exp/log/tanh/...`, `np.dot`, `np.clip`, `np.where`, `np.linalg.norm`, `np.cross`, matrix multiply (`@`), `np.sum`, branching via `fastsim.where()`, and more. Falls back to Python for unsupported patterns.\n\n## Automatic Compilation in Blocks\n\nPython functions in ODE, Function, and DynamicalSystem blocks are automatically traced and compiled. No configuration needed.\n\n```python\nfrom fastsim.blocks import ODE\nimport numpy as np\n\na, b, c = 0.04, 1e4, 3e7\n\ndef robertson(x, u, t):\n    return np.array([\n        -a*x[0] + b*x[1]*x[2],\n         a*x[0] - b*x[1]*x[2] - c*x[1]**2,\n         c*x[1]**2\n    ])\n\node = ODE(robertson, initial_value=[1.0, 0.0, 0.0])\nprint(ode.jit_compiled)  # True\n```\n\n## Custom Blocks\n\n```python\nfrom fastsim.blocks import StateSpace\n\nclass ButterworthLowpass(StateSpace):\n    def __init__(self, cutoff, order=2):\n        from scipy.signal import butter, tf2ss\n        b, a = butter(order, cutoff, analog=True)\n        A, B, C, D = tf2ss(b, a)\n        super().__init__(A=A.tolist(), B=B.tolist(), C=C.tolist(), D=D.tolist())\n```\n\nCustom blocks run at full Rust speed; only the constructor runs in Python.\n\n## Mutable Parameters\n\nAll block parameters can be modified at runtime. Setting a parameter reconstructs the Rust block automatically while preserving engine state.\n\n```python\nfrom fastsim.blocks import Amplifier, PT1\n\namp = Amplifier(gain=5.0)\namp.gain = 10.0  # instant, no performance cost\n\npt1 = PT1(K=1.0, T=0.5)\npt1.set(K=5.0, T=1.0)  # batched update, single reinit\n```\n\n## Native-CPU builds (performance)\n\nThe distributed wheels are compiled for a portable baseline (SSE2) so they run on\nany x86-64 CPU. On FMA/AVX2-heavy models the tape's scalar op loop leaves single-\ndigit-percent performance on the table because `mul_add` lowers to a libm `fma()`\ncall without hardware FMA. If you build from source for one specific machine, opt\ninto the local instruction set:\n\n```bash\n# build the extension tuned for the current CPU (FMA/AVX2 where available)\nRUSTFLAGS=\"-C target-cpu=native\" maturin develop --release\n# or for a plain cargo build\nRUSTFLAGS=\"-C target-cpu=native\" cargo build --release\n```\n\nThis is intentionally not baked into `.cargo/config.toml` — a `target-cpu=native`\nbinary may crash with `SIGILL` on an older CPU, so it must stay opt-in for\nsource builds only.\n\n## WebAssembly / Pyodide build\n\nfastsim compiles to `wasm32-unknown-emscripten` and runs in the browser via\n[Pyodide](https://pyodide.org). The FMI feature (FMU import) relies on runtime\ndynamic-library loading and is excluded from WASM builds; everything else\n(solvers, JIT tape interpreter, all blocks) runs unchanged.\n\n```bash\n# one-time toolchain setup\nrustup toolchain install nightly\nrustup component add rust-src --toolchain nightly\nrustup target add wasm32-unknown-emscripten --toolchain nightly\npip install pyodide-build                 # into your venv\n# emscripten matching the pinned Pyodide version (0.29.4 -\u003e emcc 4.0.9), e.g. via emsdk\n\n# build the wheel (writes dist/fastsim-*-wasm32.whl)\nEMSDK_DIR=/path/to/emsdk ./scripts/build_pyodide.sh\n```\n\nThe wheel installs in Pyodide with `micropip.install` and exposes the full\nPython API (`import fastsim`). Override the target release with\n`PYODIDE_VERSION=...` (must match your installed emscripten).\n\n## Code Generation (C99)\n\nAny simulation compiles to self-contained, dependency-free **C99** (libm only) —\none struct-based model you can drop into an embedded target, a HIL rig, or an FMU.\nThe generated code is reentrant by construction (all state lives in the instance\nstruct) and every extern symbol is prefixed with the model name, so two models\nlink into one binary.\n\n```python\nfrom fastsim import Simulation, Connection\nfrom fastsim.blocks import Integrator, Amplifier\n\ninteg, amp = Integrator(1.0), Amplifier(-1.0)\nsim = Simulation([integ, amp], [Connection(integ, amp), Connection(amp, integ)])\nsim.run(1.0)                       # assemble the model\n\nfiles = sim.to_c(\"decay\")          # {\"decay.h\": \"...\", \"decay.c\": \"...\"}\nfor name, src in files.items():\n    open(name, \"w\").write(src)\n```\n\n```c\n/* main.c */\n#include \u003cstdio.h\u003e\n#include \"decay.h\"\nint main(void) {\n    decay_t m;                     /* one instance struct */\n    decay_init(\u0026m);\n    decay_run(\u0026m, 1.0, 1e-3);      /* integrate to t = 1 */\n    printf(\"%.6f\\n\", m.x[0]);      /* -\u003e 0.367879 (e^-1) */\n}\n```\n\n```bash\ncc decay.c main.c -lm -o decay \u0026\u0026 ./decay\n```\n\nThe emitted API, compiler requirements, and the ABI stability policy are\nspecified in **[doc/codegen.md](doc/codegen.md)**. Passing options to `to_c(...)`\n(numeric type, `layout=\"library\"`, solver, `structure=\"flat\"`) is documented\nthere and in `help(Simulation.to_c)`.\n\n## License\n\nfastsim is licensed under the [PolyForm Noncommercial License 1.0.0](LICENSE):\n**free for noncommercial use** (research, teaching, academia, personal and hobby\nprojects). Commercial use, **including shipping fastsim-generated C code in a\ncommercial product**, requires a commercial license.\n\nThe generated C code is \"Output\" under the license and carries the same\nnoncommercial limitation; each generated file is stamped with this notice.\n\nFor commercial licensing — including shipping fastsim-generated C in a product —\nsee **[COMMERCIAL.md](COMMERCIAL.md)** or contact **info@pathsim.org**.\n\nNeed a fully open-source option? The pure-Python implementation,\n[pathsim](https://github.com/pathsim), is available separately under the MIT\nLicense with no field-of-use restriction.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpathsim%2Ffastsim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpathsim%2Ffastsim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpathsim%2Ffastsim/lists"}