Equivalent-circuit cell
A Thevenin 1-RC cell — series resistance, one RC polarization pair, a non-linear OCV(z) curve and coulomb-counted state of charge — written once and reused at every level.
An electric-vehicle battery pack as one multi-domain model — equivalent-circuit cells, a coupled thermal network, a CC-CV charge controller and an active balancer, composed cell → module → pack and run end to end.

Cell electrochemistry, pack thermals, and the battery-management system don't live in separate tools here. A 96S2P NMC pack is built as one composition — equivalent-circuit cells coupled to a thermal network, wrapped in a closed-loop CC-CV charger and an active balancer — and solved together, electrical and thermal and control in a single elaboration.
A single equivalent-circuit cell is the atom; the module and pack are compositions of it. Each layer is its own runnable model, and they share one cell definition.
A Thevenin 1-RC cell — series resistance, one RC polarization pair, a non-linear OCV(z) curve and coulomb-counted state of charge — written once and reused at every level.
Ohmic and polarization loss become heat that drives a lumped thermal mass with convective bleed to ambient. Temperature is a first-class state, not an afterthought.
A saturated-proportional control law reads pack voltage and commands a charge current — reproducing the textbook constant-current → constant-voltage envelope without any mode-switching events.
A charge-shuttling balancer moves charge between imbalanced cells toward the module mean — conserving total charge while the spread collapses in minutes.
An Extended Kalman Filter fuses noisy voltage and biased current to track SoC online, where a bare coulomb counter would drift.
An over-temperature throttle with hysteresis derates the charge current to hold the hottest cell at its cap — the BMS protecting the pack, in the loop.

The acausal electrical network, the per-cell heat path, and the signal-domain control loop are elaborated into one differential-algebraic system that a stiff Rodas5P solver integrates as a whole — no co-simulation hand-off, no manual time-stepping between tools. A 1C discharge of the cell drops SoC from full to 16.7%, sags the terminal from 4.10 V to 3.21 V, and lifts the cell about 1.4 °C, all from the same coupled equations. The same model exports as an FMI 2.0 co-simulation unit for Simulink, dSPACE and other FMI hosts.

Run the pack over a mixed charge/discharge profile with a noisy voltmeter and a biased ammeter. A pure coulomb counter — the cheap baseline — walks off to about 5% SoC error. The Extended Kalman Filter on the cell's [SoC, polarization] state corrects from the voltage residual and ends within 0.07% of truth, holding under ~0.7% after the first few minutes — comfortably inside a 2% accuracy budget.

The charge controller commands a current proportional to the gap between pack voltage and the CV set-point, clamped to a maximum. Far from the set-point it saturates — that's the constant-current phase; as the pack fills, the command falls out of saturation and tapers — that's constant-voltage. Sweeping the current limit against peak temperature finds the knee: about 3.1C reaches 80% state of charge in 25 minutes while staying inside the thermal limit.

Terminal current is defined positive into the + pin, so positive current charges. A discharge load forces +I into its own pin and Kirchhoff's law makes the cell see −I — get that backwards and the pack silently charges instead of discharging.
The canvas engine rejects a single component that bridges two acausal domains, so the cell can't carry both an electrical and an acausal thermal port. Heat is emitted as a signal and integrated by a thermal block instead — same physics, a model that actually compiles.
The charge current appears in the measured pack voltage through the ohmic drop, closing an algebraic loop. The saturated proportional law keeps it well-posed, and the solver resolves it every step — confirmed against an analytic CC→CV cross-check.
Each cell exchanges a current proportional to its distance from the module mean. The corrections sum to zero, so the average SoC is preserved exactly while the spread decays — active shuttling, not dissipative burn-off.
The notebooks and .djl studies are gated on verified live-worker results, with the physics cross-checked by independent integration of the same equations.
The cell, module and pack are pure-text DJL. The parser lowers them to a flat intermediate representation, then to a ModelingToolkit symbolic system the Julia worker integrates — streaming live scopes back into the browser — and the catalog circuits export as functional FMI units. Eleven notebooks carry the engineering narrative end to end: OCV characterization, equivalent-circuit identification, thermal C-rate response, SoC estimation, balancing, BMS control, fast-charge trade-offs, cycle and calendar aging, and a full drive cycle — a design-iteration twin you exercise long before a cell is ever assembled.
The cell is an equivalent-circuit surrogate, not an electrochemical (Newman P2D / single-particle) model — it captures voltage, state of charge and lumped heat, not concentration gradients, plating or detailed degradation chemistry. OCV is a smooth analytic curve in the .djl atom and the realistic NMC/LFP shapes live in the notebooks; aging is empirical (Arrhenius throughput and calendar laws). What it is good for is exactly what pack and BMS design needs first: sizing series/parallel counts, choosing the thermal budget, tuning the charge and balancing strategy, and trading fast-charge speed against heat — on your own cell numbers, in minutes, before any hardware exists.
Keep exploring