Modelica.Electrical.Batteries coverage

Modelica.Electrical.Batteries (Modelica Standard Library 4.0.0) is the reference lumped battery library: an open-circuit voltage controlled by the state of charge, a self-discharge conductor, an inner resistance and optional RC elements, wrapped in a stack of Ns × Np cells. This page maps every component and every parameter of it onto its equivalent here, so that a reader coming from Modelica can find what they already know, and so that the places where the two libraries genuinely differ are written down rather than implied.

Two conventions differ throughout and are not repeated in the tables:

  • Modelica's Qnom is a charge in coulombs; "nominal capacity" here is in A⋅h.
  • Modelica's i is the current into the battery; the reported I here is discharge-positive, I = -p.i. The pin convention is the same.

Components

ModelicaHereNotes
BatteryStacks.CellStackRintAn open-circuit voltage in series with a resistance. Modelica's is a single lumped cell scaled by Ns and Np; a BatteryPack of identical Rint cells reproduces its stack scaling exactly, which test/modelica_coverage.jl checks.
BatteryStacks.CellRCStackThevenin(n), DP for n = 2nRC RC pairs in series behind the ohmic resistance.
BatteryStacks.SuperCap—An ultracapacitor rather than a battery; tracked separately in issue #206.
BatteryStacksWithSensors.Cell, CellRCBatteryCellA cell here is the 1 × 1 pack, so the cell and the stack are the same builder.
BatteryStacksWithSensors.Stack, StackRCBatteryPack(; series, parallel)A matrix of individually parameterized cells.
Interfaces.CellBus, StackBus, StackBusArrayspack outputs and cell_viewsPer-cell voltage, current, state of charge, temperature and loss are already (series, parallel) arrays; cell_views(pack)[s, p] addresses one cell.
Utilities.BusTranscription—Not needed: the pack quantities are arrays over the grid to begin with, so there is nothing to transcribe from a bus into a matrix.
Utilities.CCCVchargerCycler with [charge(1C), voltage(hold)]Constant current until the end-of-charge voltage, then constant voltage.
Utilities.PulseSeriesa Cycler protocol vectorA series of current(…) and rest(time = …) steps, with per-step amplitudes and durations rather than two fixed pulse trains.
Utilities.Impedance—A block evaluating the closed-form complex impedance R0 + Σₖ (1/Rₖ + 2πf Cₖ i)⁻¹ at a frequency input. It is a formula over the same parameters rather than a model of the cell, so it is deliberately not provided.

Cell parameters (ParameterRecords.CellData)

ModelicaHereNotes
Qnom"nominal capacity" in overallIn A⋅h.
useLinearSOCDependency, OCVmax, OCVmin, SOCmax, SOCminlinear_ocvThe same straight line. clamped = true, the default, holds the endpoint values outside the window, which is the HoldLastPoint extrapolation Modelica's table lookup uses.
OCV_SOC[:,2], smoothnessLookupTable, or any (SOC, T) callablePartly. LookupTable(; soc = OCV_SOC[:, 1], values = OCVmax .* OCV_SOC[:, 2]) is the same table under Modelica's default smoothness = LinearSegments, with the same HoldLastPoint extrapolation (Modelica's table holds normalized voltages, so they are scaled by OCVmax). The smoother smoothness settings, such as the ContinuousDerivative of Modelica's example records, have no table counterpart; a smooth curve can be given as a closed-form callable instead, as ChenRinconMora2006's fit is.
Ri, R0"series resistance"Modelica's Ri is the total inner resistance and R0 = Ri - sum(rcData.R) is derived from it. "series resistance" here is R0 directly, so the total is R_0 + Σₖ R_k.
T_ref, alphalinear_resistanceThe same law, R = R_ref (1 + α (T - T_ref)). It applies to any resistance entry, so each RC branch can carry its own coefficient. It varies only in a cell built with temperature = true.
Idis"self-discharge current" in overallThe current drawn at full charge, parameterized exactly as Modelica's parallel conductor: the conductance is that current over the open-circuit voltage at full charge, so the loss falls with the state of charge.
SOCtolerance, the SOC range assertionsbounds "state of charge minimum" and "maximum"Deliberately different. Modelica clamps its integrator at 0 and 1 and raises an error outside SOCmin … SOCmax. Here the bounds are Cycler stop conditions: the step terminates on them instead of the run failing.

Transient parameters (ParameterRecords.TransientData)

ModelicaHereNotes
nRCthe order of Thevenin(n)
rcData[k].R, rcData[k].C"polarization resistance", "polarization capacitance"Vectors of n entries, in the same order.
rcData[k].T_ref, rcData[k].alphalinear_resistance per entryModelica documents the RC resistors as sharing the temperature dependency of Ri; here each entry carries its own, so the shared case is a repeated argument rather than a constraint.

Stack parameters (ParameterRecords.StackData)

ModelicaHereNotes
Ns, Npseries, parallel
SOC0[Ns, Np]SOC_initial, shape (series, parallel)
kDegraded[:,2], cellDataOriginal, cellDataDegradedparameter_values with (series, parallel) arraysMore general here. Every cell parameter is already an array over the grid, so any cell can take any value; Modelica's record indirection expresses the special case of two populations selected by an index list.
useAllParallelConnectionswiringtrue is :parallel_groups, the default; false is :series_strings. See Wiring order.
useHeatPort, heatPort[Ns, Np]temperature = true and two ArrayHeatPortsDeliberately different. Modelica gives every cell its own heat port and no conduction between cells. Here each cell has a heat capacity, parallel neighbours within a series row share a thermal node, and the two ports are the row boundaries; PackThermalNetwork adds cell-to-cell and cell-to-coolant conductances.

Wiring order

Modelica's matrix stack offers two orders, and so does BatteryPack:

pack = BatteryPack(; name = :pack, model = Rint(), series = 3, parallel = 2,
    wiring = :series_strings)
  • :parallel_groups (useAllParallelConnections = true, the default here too) wires parallel cells in parallel and those groups in series.
  • :series_strings (useAllParallelConnections = false) wires series cells in series and those strings in parallel.

Identical cells divide the current evenly under either order, so with ideal wiring the two are indistinguishable until the cells differ — which is the case a matrix stack exists to study. Modelica's matrix stack is ideally wired throughout, which is R_branch and R_link all zero.

Nonzero connection resistances do separate the two even for identical cells, because the links are in different places. R_branch stays in series with its own cell either way, but with :parallel_groups all series + 1 links carry the pack current, while with :series_strings the interior links R_link[2:series] sit inside each string and carry that string's current — a parallel-th of the total — and only R_link[1] and R_link[series + 1] carry the pack current.

The wiring is an argument of the Julia BatteryPack builder. The Dyad ArrayBatteryPack component does not expose it and always uses :parallel_groups.

Beyond the Modelica library

These have no counterpart in Modelica.Electrical.Batteries and are not claimed as coverage of it; they are listed so the mapping above is not mistaken for the whole API.

  • Open-circuit voltage as a function of temperature as well as state of charge. Modelica states that it "would require a 2-dimensional table look-up" and does not implement it; an "open-circuit voltage" entry here takes (SOC, T), and a LookupTable over both axes is that table look-up.
  • Separate "discharge resistance" and "charge resistance" selected by the sign of the current, and a "nominal capacity" and "coulombic efficiency" that follow the cell temperature, as the Rint model of SaftLiIon6Ah uses.
  • Reversible entropic heat, through "entropic coefficient".
  • The PNGV and RCModel topologies, and "coulombic efficiency" on the coulomb counter.
  • Externally prescribed capacity health and resistance growth, per cell.
  • The electrochemical models SPM, SPMe and DFN, which reach the same pack builder.

What the tests check

test/modelica_coverage.jl runs the claims in these tables that are claims about behaviour rather than about naming:

  • the linear open-circuit voltage matches OCVmax, OCVmin, SOCmax, SOCmin at the endpoints and at an interior point, and holds its endpoints outside the window;
  • a resistance built with linear_resistance moves the terminal voltage by I R_ref α (T - T_ref);
  • a series × parallel pack of identical cells reproduces Modelica's lumped stack scaling: OCVmax Ns, Ri Ns / Np and Qnom Np;
  • the two wiring orders agree for identical cells and disagree for a degraded one, and the series-strings network matches an independent nodal analysis;
  • per-cell heterogeneity, the kDegraded analogue, reaches individual cells: each cell of a mixed resting series string holds its own open-circuit voltage, while ideally connected parallel neighbours share one node and settle at the mean of theirs, circulating current between themselves at zero pack current;
  • none of the above costs the pack its size-independent symbolic equation count.

That last one is a claim about the symbolic system, not about compilation. mtkcompile scalarizes array equations by design — an array state of length n becomes n equations whatever its right-hand side — so the test counts equations on the system before compilation, which is the form the array design is about.