Releases: OpenMagnetics/PyOpenMagnetics
Release list
v1.7.2
Built against MKF 75afbb6f.
Complex permeability stopped falling above a few MHz (ABT #843)
calculate_complex_permeability returned a constant above a few MHz. For Nanoperm 80000 it handed back the same mu' = 19210.6, mu'' = 13647.3 at 4.33 MHz, 10 MHz, 25.6 MHz, 50 MHz and 100 MHz — while the material's own initial-permeability table falls to 156 by 25.6 MHz, so the engine was 151x high there.
Three independent causes, all pushing the same way:
- The tabulation was too short. The generated table spanned only
0.01x-100xthe anchor frequency, and the lookup clamps to that range. A material anchored at 18.8 kHz tabulated 188 Hz - 1.88 MHz, so every frequency above 1.88 MHz read back the last point. Widened to0.01x-1e5xat the same ~10 points per decade. mu'did not follow the material's own data. The closed form rolls off as ~1/sqrt(f) (the sheet solution) while a nanocrystalline material falls closer to ~1/f; unfrozen it still read 7,375 at 25.6 MHz.mu'is now rescaled onto the measured curve, carryingmu''at the modelled loss angle, so the paper's gap correction and loss shape are kept while the magnitude follows the data.- The interpolator turned back UP past its last point (156 -> 451 at 50 MHz -> 1,057 at 100 MHz). Permeability does not recover after roll-off; the tail now continues with the slope from the material's own last two points, floored at zero so it can never climb.
Nanoperm 80000, |mu|:
| f | before | after | material's table |
|---|---|---|---|
| 1 MHz | 30,116 | 2,822 | 2,378 |
| 4.33 MHz | 23,565 | 773 | 641 |
| 25.6 MHz | 23,565 | 184 | 156 |
| 100 MHz | 23,565 | 72 | (extrapolated) |
Why it matters downstream: this drove sweep_common_mode_impedance_over_frequency. WE part 7448014501 simulated a peak of 7,651 ohm at 4.33 MHz; the measured part peaks at 1,090 ohm on a broad plateau from 43 to 58 MHz (WE RedExpert and the published datasheet graph agree to within 1%). Anything sweeping impedance or permeability past a few MHz was affected.
Also in this release
fix(energy)— a MAS getter returning by value was bound to aconst&and read after the temporary died. It reported magnetizing peaks of ~3.3e6 A instead of ~5 A and could silently empty the CoreAdviser candidate list.test(core-losses)— DMEGC DMR51W's known-red case is tagged[!mayfail]so it reports as expected rather than as a failure.
Known issue shipping with this release
ABT #842 — a test-isolation leak: process-global state survives settings.reset() and clear_databases(). Harmless in a test binary that exits, but PyOpenMagnetics is a long-lived process that does not restart between designs, so repeated advising in one process may be affected. Pre-existing, not introduced here.
Verification
MKF: [impedance] 13/13 including Test_Impedance_Complex_Permeability_No_Extrapolation, all five permeability tests, and [core-losses] identical to the pre-change baseline (65 cases, 5,735 assertions). A new regression test pins that the curve keeps falling and tracks the material.
Note MKF_FORCE_REFRESH is bumped alongside the version: FetchContent pins MKF_GIT_TAG to the moving main, so without a new cache-busting string a build can reuse an older cached clone and ship without the fix.
v1.7.1
Built against MKF e0fb636d, which contains the ABT #823 wire fix.
Catalogue loading is fixed (ABT #823)
Loading a magnetics catalogue would die with an anonymous bad optional access on any record whose wire is supplied inline with no outer size (conductingDiameter + coating, no outerDiameter) on a coil that is not pre-wound. magnetic_autocomplete ends in coil.wind(), which read the outer dimension as a bare .value().
- MKF now derives the missing outer dimensions from the conductor and its coating, and where it genuinely cannot, throws
[INVALID_WIRE_DATA]naming the winding index, winding name and the magnetic's reference. load_magnetics_from_fileis now atomic. The file is parsed into a staging vector and committed only if every record survives, so a failed load leaves the cache at 0 rather than partly populated. Previously it stopped at the first bad record and left everything before it loaded — a truncated catalogue that looked healthy.- Failures name the record:
<path>:<line> (part '<reference>'): <reason>. - A record with no
manufacturerInfo.referenceis a named error rather than a second anonymous optional access. - A file that cannot be opened now raises instead of returning the cache size.
Measured on a 236-part common-mode-choke catalogue: previously a hard failure at record 78 with 77 parts cached; now all 236 load in ~2 s.
Winding-loss numbers change (ABT #832)
This release carries an FEM-arbitrated (2D OMFEM) correction to the loss models. Anything that pins or snapshots winding loss, R_ac, or efficiency will move. This is a correctness improvement, not a regression, but it is not silent:
- Rectangular-wire proximity loss was ~1000x under (a dimensionally wrong prefactor); now within 3% of FEM at 5 turns.
- Gapped fringing was up to 53x over on a 2 mm-gap ETD24; now tracks FEM.
- Residual (5 um mating-surface) gaps no longer fringe at all.
Known limitations, stated deliberately
- The loss residual grows with conductor packing: 7-turn rectangular +21%, ten toroidal turns +35-62% vs FEM.
- Foil beside a gap is missing its dominant current-crowding term entirely (ABT #836).
- Most user-selectable non-default loss models are still wrong (ABT #837). The defaults are the good path.
New bindings
load_magnetics_from_file_report(path, expand)/load_magnetics_from_string_report(...)— return{'loaded', 'cacheSize', 'rejected': [{'line', 'reference', 'reason'}]}, caching the good records and never throwing on a bad one. Strict loading stays strict; tolerance is a separate function name so a truncated catalogue cannot become the default by accident.get_core_material_available_losses_methods(material_json)— asks the loss-methods question of a material directly, so a caller comparing materials need not build aMagneticaround each one.
Other fixes
calculate_advised_cores/_magnetics: six result loops dereferenced the optionalmanufacturerInfoand itsreferenceunconditionally, killing the whole call at the very end — after every candidate had been advised and scored — for a catalogue entry that simply had no reference (ABT #825).- Test suite: xfails and skips that no longer described reality have been removed (ABT #824), including the core-adviser timeout skip.
v1.6.6
Complete Halo Cosmos set — 46 grades (ABT #575).
No code change over 1.6.5. 1.6.5 shipped 42 of the 46 Halo Cosmos NiZn grades; TFH, TBH, SFK and STF were in the same published table and were lost to a digit-requiring regex in the import, not to anything about the source.
It was caught by installing the published 1.6.5 wheel from PyPI and spot-checking grade names against it — i.e. by reading back the shipped artifact rather than re-checking the intermediates, which all agreed with each other because they shared the same bad filter.
| grade | mu_i | Bs | Tc |
|---|---|---|---|
| TFH | 400 | 0.450 T | >250 °C |
| TBH | 200 | 0.410 T | >300 °C |
| SFK | 400 | 0.460 T | >230 °C |
| STF | 350 | 0.410 T | >210 °C |
MAS da3b723 via MKF 8139ba9c: 707 material records, 46 Halo Cosmos grades.
1.6.5 remains valid and stays on PyPI — the four additions are grades no known part uses, and S4H (the grade that prompted the batch) was already in 1.6.5.
v1.6.5
Multi-grade drum+ring cores (ABT #576).
A shielded drum and its closing ring are routinely different grades — WE-DPC-6040 is an ACME P47 drum (MnZn, mu_i 3000) inside an ACME B45 ring (NiZn, mu_i 450). Until now functionalDescription.material named a single grade, so whichever was chosen, the other piece was modelled as something it is not.
What's new
functionalDescription.materialmay be a list for assemblies whose pieces are different grades, primary piece first (MAS 21b02d37).drumRingapplies the drum permeability to the drum sections and the ring permeability to the ring sections (MKF b01e91a7).Core::resolve_materials()alongside the unchangedCore::resolve_material(), which still returns the primary piece — no call-site changes.- Material database gains S4H (the grade behind WE-DPCHV) and 41 further Halo Cosmos NiZn grades, plus corrected saturation records for
2HC_283,1LH_48,1HC_151and1MA_23, which previously read B_sat 2.8–3.0x low because a whole B(H) sweep sat in thesaturationfield.
Verified
- five single-material drumRing grades identical to their pre-change values;
- a two-material core lands at median L_mkf/L_vendor 1.155, inside the 1.029..1.180 bracket a per-section blend must fall in, and equal to neither endpoint;
- the material list survives re-resolution, and an over-long list throws;
- the 504-part Würth corpus is byte-identical to its reference (504/504 SPICE export, L median 1.023, p10 0.825, p90 1.193, 84% within ±20%).
1.6.3
1.6.2
PyOpenMagnetics 1.6.2
- Binds
sweep_common_mode_impedance_over_frequency(ABT #167) — the parallel-winding common-mode impedance sweep El Choker needs; 1.6.1 predated it. - Built against MKF
main: complex-permeability derivation + up-to-date POCO material lineup.