PowerDynamics v5.0.0
Version 5.0.0 Changelog
Two themes: the ecosystem move that comes down from
NetworkDynamics v1.0/v1.1
(ModelingToolkit v11, the reworked initialization pipeline, SciML v3), and a per-unit
overhaul that turns base values from per-device constructor arguments into a property of
the bus and line.
The library saw a broad naming and unit cleanup in the process. Renamed parameters fail
loudly at construction, so the practical upgrade path is to build your models and follow
the errors — check the docstrings for anything that no longer takes the argument you
pass it. The parts that change numbers rather than names are called out explicitly
below.
Breaking: ecosystem
- All NetworkDynamics v1.0 breaking changes apply unchanged. PowerDynamics
@reexports NetworkDynamics, so its API is part of the PowerDynamics API — most
notablyset_mtk_defaults!→ non-mutatingset_mtk_defaults, symbolic expressions as a
guessnow error in favour ofinitf/guessf,find_fixpointtakes anNWState, and
MTK models are no longer simplified bymtkcompile. See the
NetworkDynamics release notes
for the details and the rewrites. NetworkDynamics ≥ 1.1.0 is required. ModelingToolkit→ModelingToolkitBase+SciCompDSL
(#261). MTK v11 split into
ModelingToolkitBase(MIT) andModelingToolkit(AGPL); PowerDynamics depends only on
the MIT half, and@mtkmodelmoved out intoSciCompDSL. Along with it:Symbolics≥7,
SciMLBase≥3 and theOrdinaryDiffEq*subpackages ≥2.- The
Bus(...)/Line(...)deprecations are removed; usecompile_bus/compile_line.
Breaking: per-unit system
Base values are now part of the model structure rather than something you pass to each
device. There is a new documentation chapter, "Per-Unit Systems", that explains the
whole scheme; the short version:
- Global bases with accessors: a system power base (100 MVA), frequency base (2π·50
rad/s) and fallback voltage base, set through the new exportedset_Sbase!,
set_ωbase!/set_fbase!andset_Vbase!(plusget_*counterparts). They are read at
model construction, so set them before building anything. - New
SystemBasecomponent carries the global quantities (Sbase,ωbase,ωframe).
Exactly one instance namedsystembasesits at the top level of every bus and line;
MTKBus/MTKLine/compile_bus/compile_lineplace it for you. BusBarandLineEndcarryVbase, the one genuinely local base, along with derived
Ibase/Zbase/Ybaseand SI observables (u_kV,P_MW,Q_MVAr,i_kA).Sbaseis a
three-phase power andVbaseline-to-line, henceIbase = Sbase/(√3·Vbase)— the exported
helperIbase(S, V)changed accordingly.- Devices inherit their bases and no longer take
S_b/V_b/ω_b. Drop those arguments
at the call site: set the power/frequency base globally and the per-bus voltage base with
the newMTKBus(…; Vbase=…)/compile_bus(…; Vbase=…)keyword.Vbasepropagates
outward from there — a line end inherits from the bus it connects to (a transformer is
just a line whose two ends resolve differently, ratio included), and a satellite/injector
bus inherits from its hub. An explicitly set value always wins. Sn/Vnare now optional, weakly defaulting to the bus base, so a machine running on
the system base needs no rating at all.LineEndrequires asidekeyword (:src/:dst) — it selects which bus the end
inherits from.MTKLinepasses it automatically; hand-rolled line models must be updated.- New
check_base_consistency(s::NWState), run automatically byinitialize_from_pf[!]
(check=:errorby default,:warn/:noneto downgrade), verifying that the global bases
agree everywhere and that every line end and satellite bus matches the bus it hangs off.
Breaking: naming and units in the library
-
Setpoints are spelled
…set(Pset,Qset,Vset,ωset, …);n/nomis reserved
for genuine nameplate ratings (Sn,Vn). Models ported from elsewhere keep their
source's names so they can still be checked against the original — the AVRs'vrefand
the governors'ω_ref/p_refare unchanged. -
EMT components name parameters for what they hold: reactance
Xand susceptanceB
instead ofLandC, which stored reactance/susceptance values all along. The topology
is in the model name, so there is no ambiguity. -
Frequency vocabulary is split three ways. One symbol used to do three unrelated jobs:
symbol kind unit meaning ωbaseunit rad/s converts SI time ↔ pu; the frequency at which X = ωbase·L,B = ωbase·Cwere evaluatedωframegauge pu speed of the global dq frame; pinned to 1ωsetsetpoint pu frequency a droop/damping law is commanded to hold Consequences throughout the library: an
ω0 = 2π*50keyword on the dynamic shunts,
branches andComposableInvertermodels is gone (they takeωbasefrom the bus instead),
every place where the reference frame was an invisible literal1now writesωframe,
and the dq cross-coupling terms of the EMT components gained theωframefactor they were
missing. Sinceωframe == 1these are all algebraically identical to before — the OpenIPSL
comparison tests pass unchanged. -
Three models genuinely change behaviour and their parameter sets do not carry over:
SwingandIdealDroopInverterhad noωbaseat all, so withωin pu the
angle advanced ~314× too slowly. Both now useDt(θ) ~ ωbase*(ω - ωframe).Swing's
Mis the inertiaM = 2Hin seconds (default6.0, i.e.H = 3 s) andDa damping
power coefficient in pu/pu (default2.0);IdealDroopInverter'sKpis a pu droop
(default0.05). Retune existing parameter sets against these units. A physically sized
machine is lightly damped, so call sites that want a quickly settling transient now pass
aDwell above the default.DroopOuter/DroopInverter:ωis now pu rather than rad/s, makingKpa
dimensionless droop (default0.05). Convert an existing value with
Kp_new = Kp_old/ωbase— with that substitution the rewrite is an exact identity, and
the linearization is unchanged.
IdealDroopInverterandDroopInverternow also share the same droop defaults
Kp = Kq = 0.05; they previously disagreed onKq, so swapping one model for the other
silently changed the voltage stiffness. -
Smaller renames in the same spirit —
VoltageDependentLoad'sVn→Vset,
PSSE_GENCLS's output portωout→SPEED_out, and unified state/output names on the
two PLLs. Consult the docstrings.
Initialization
- Backward initialization through nested components. NetworkDynamics' new
initf/guessfmetadata lets each model carry its own init recipe; composed together
they chain into a DAG that can fix every free variable from the powerflow alone, with no
nonlinear solve at all. The new tutorial "Backward Initialization of Nested Models" builds
a full generator bus that initializes to "No free variables!", and a new "Advanced
Initialization" documentation chapter covers the mechanics. @pfinitconstraint/@pfinitformulahygiene fixed: both macros mishandled escaping, so
a constraint could not close over local runtime variables. They now capture locals
correctly andshowprints the macro form you wrote.initialize_from_pfno longer ignorespfs0— the supplied start state was
overwritten with the powerflow network, so a hand-tuned guess had no effect.tol/nwtol
are now forwarded to the residual check.
Library
- Optional stator dynamics in
SauerPaiMachineviaSauerPaiMachine(; stator_dynamics=true). compile_bus/compile_lineaccept a bare injector/branch, wrapping it in
MTKBus/MTKLineautomatically instead of erroring.- New
mtkcompilekeyword oncompile_bus/compile_line, forwarded to
VertexModel/EdgeModel. - Bug fixes:
ClassicalMachine's Park transform applied the current base ratio upside down
(wrong currents wheneverSn ≠ Sbase); a disconnectedComposableInverterkept driving
its LCL filter and wound up to ≈70 pu internally; limited-integrator callbacks now resolve
the integrator state through the observed-alias chain instead of assuming a name survives
compilation (visible inPSSE_HYGOV);TurbineGovTypeIcould not be constructed at all
(it is constructible now, but remains untested — there is no reference trajectory for it). - Saturation functions (
QUAD_SE,EXP_SE,PSSE_ESST4B'sFEX_function) are AD-safe and
useNaNMath, so a slightly out-of-range argument no longer throws aDomainError
mid-initialization.
Documentation
- New chapters: "Per-Unit Systems" and "Advanced Initialization" (see above).
- New "Getting Started with Julia" section
(#276): the setup page was
rewritten and joined by "Environment Management" and an opinionated "How to Structure
Research Projects" guide, aimed at users who arrive at PowerDynamics before they arrive at
Julia. - New tutorial "Backward Initialization of Nested Models"; the EMT toymodel example was
overhauled, and the initialization and modeling-concepts chapters were reworked for v5.
Merged pull requests:
- Bump actions/upload-artifact from 6 to 7 (#257) (@dependabot[bot])
- Bump julia-actions/cache from 2 to 3 (#258) (@dependabot[bot])
- MTK@v11 Compat (#261) (@hexaeder)
- Bump julia-actions/cache to v3, remove cache-save workaround (#264) (@hexaeder)
- Bump julia-actions/setup-julia from 2 to 3 (#269) (@dependabot[bot])
- Add opinionated guide on how to structure julia research projects to docs (#276) (@hexaeder)
- Change initial guess for rotor frequency to 1 (#277) (@Sciemon)
- Bump codecov/codecov-action from 5 to 7 (#279) (@dependabot[bot])
- Bump actions/checkout from 6 to 7 (#282) (@dependabot[bot])
- Bump SciMLBase 2->3 ecosystem (#284) (@hexaeder)
- Adjust PD for init overhaul in NetworkDynamics (#288) (@hexaeder)
Closed issues: