PESLite
Time-domain simulation of power-electronic converters in Python.
- Networks of buses, lines, grid sources and any number of converters, defined in YAML.
- Grid-following (PLL, current loop, dc-voltage loop) and grid-forming control (PSC, droop, VSG, dVOC, matching), each loop on its own clock.
- Switching (ideal switches, exact switching instants), averaged and step-averaged bridges.
- Fixed-step, adaptive (SciPy or built-in DP45) and multirate integration.
- ADC sampling (instantaneous or window average), computation delay, PWM, protection.
- Energy accounting of the power circuit and restart from any saved state.
The power circuit works in SI units (V, A, H, F, ohm); controllers work in pu of each converter's own base. Time is in s, angles in rad.
Installation
python -m pip install -e . # numpy, scipy, PyYAML
Python 3.10 or newer.
Quick start
# run the first configuration in configs/ (sorted by name)
python peslite.py
# run a configuration by name or path; results go to output/<name>/
python peslite.py gfl
python peslite.py configs/gfm-psc.yaml --out output/psc
# Run your own configuration
peslite case.yaml
peslite ./configs/my-converter.yaml
# A suffix may be omitted
peslite case
# Bundled examples are also available by name
peslite gfl
peslite gfm-psc
peslite gfm-droop
# override any parameter by its dotted path
python peslite.py gfl --set simulation.t_end=1 --set units.vsc.delay.steps=1
python peslite.py gfl --set simulation.solver.type=adaptive --set simulation.solver.method=DP45
python peslite.py gfm-droop --set simulation.bridge=switching
# continue a run from its last saved state (or from time T with --initial-time T)
python peslite.py gfl --out output/a
python peslite.py gfl --initial output/a/states.csv --out output/b
# inspect a configuration
python peslite.py gfl --list-states # state names (the states.csv columns)
python peslite.py gfl --ph-report # port-Hamiltonian structure of the circuit
python peslite.py --help
From Python (in this folder, or anywhere after pip install -e .):
import peslite
p = peslite.load("configs/gfl.yaml", **{"simulation.t_end": 1.0})
r = peslite.Simulation(p).run()
r.states["plant.vsc.dclink.u_C"] # a state over time
r.plant["vsc.i_c"] # plant signals (complex space vectors)
r.control["vsc.id_pu"] # controller log of unit "vsc"
r.final_states() # last row, usable as an initial state
r.summary # trips, alarms, peaks
r.save("output/run") # states.csv, summary.json, params.yaml
Example configurations
| File | Content |
|---|---|
configs/gfl.yaml |
Grid-following converter; every key is annotated |
configs/gfm-psc.yaml |
Grid-forming, power-synchronization control |
configs/gfm-droop.yaml |
Grid-forming, droop with virtual admittance and current loop |
configs/gfm-vsg.yaml |
Grid-forming, virtual synchronous generator |
configs/gfm-dvoc.yaml |
Grid-forming, dispatchable virtual oscillator control |
configs/gfm-matching.yaml |
Grid-forming, matching control |
configs/two-converters.yaml |
A grid-forming and a grid-following unit on one grid |
Frequently used settings
| Path | Values |
|---|---|
simulation.t_end |
end time, s |
simulation.bridge |
switching | averaged | step_averaged |
simulation.solver.type / .method |
fixed: euler | heun | rk4; adaptive: RK45 | DOP853 | Radau | BDF | LSODA | DP45 |
simulation.solver.dt |
maximum fixed step, s |
simulation.solver.subsystems |
own steps per subsystem, e.g. {vsc.dclink: 10, pcc: 0.1} |
simulation.log.plant_period |
snapshot interval, s |
simulation.energy_check |
warn | strict | off |
units.<u>.control.type |
gfl | gfm | custom |
units.<u>.control.loops.<loop>.period |
loop period, s |
units.<u>.measurement.average |
instantaneous | window (with window_s) |
units.<u>.pwm.method / .sync |
spwm | svpwm; asynchronous | synchronous |
units.<u>.delay.steps |
computation delay in PWM updates |
output.states / .signals / .energy |
which files are written |
Output
| File | Content |
|---|---|
states.csv |
every state at each snapshot; any row can start a new run |
plant.csv, control.<unit>.csv |
plant signals and controller logs (output.signals: true) |
energy.csv |
stored energy and power balance (output.energy: true) |
summary.json, params.yaml |
run summary and the full parameter set |
Custom parts
# replace one control loop's algorithm
ctrl = peslite.UniteType(p.unit("vsc"), loop_overrides={"pll": MyPLL()})
sim = peslite.Simulation(p, instances={"vsc.ctrl": ctrl})
# or pass a factory, so the part can be rebuilt
sim = peslite.Simulation(p, parts={"vsc.ctrl": lambda cfg: peslite.UniteType(cfg)})
Other replaceable parts: pwm_method= and limiter= of UniteType, <unit>.modulator,
<unit>.delay, solver, and extra circuit elements through System(p, elements=[...]).
See examples/custom_plant.py (custom network section, synchronization law and solver) and
examples/compare_solvers.py.
Layout
The repository folder is the peslite package.
peslite.py command line
simulation.py simulation loop
__init__.py package exports
phs/ circuit model, energy accounting, solvers
params/ parameter schema, validation, file I/O
power/ sources, lines, buses, bridge, dc link
control/ PLL, current and dc-voltage loops, grid-forming laws, control graph
firmware/ pu conversion, limiter, delay, transforms
modulation/ PWM methods and modulators
sensing/ ADC sampling
protection/ relay
results/ recording and result files
assembly/ converter unit, system assembly
configs/ example configurations
examples/ usage examples
License
GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE.
Metadata
Release files for peslite 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| peslite-0.1.0.tar.gz | 121.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| peslite-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 265.8 kB
Release files / peslite-0.1.0.tar.gz
| Download URL | peslite-0.1.0.tar.gz |
|---|---|
| Size | 121.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6e2777db768e4f47644d55e8df7891157ace5876b6133c1a6b30e368160ce510
|
|
BLAKE2b-256 checksum How to use checksums |
ccca899f9b16ec8ff18c656d86487270f34a49fabf200b9d31f57255c80270c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / peslite-0.1.0-py3-none-any.whl
| Download URL | peslite-0.1.0-py3-none-any.whl |
|---|---|
| Size | 144.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b01e2239802b01da62ec73135bae6718fe0651fcb5a82d3be3561e2b8d6fae83
|
|
BLAKE2b-256 checksum How to use checksums |
beab0f460edf6319036b9e65333bbbb8a5b330e79e28547c0fbc335a425efd86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log