PyOpenMagnetics 1.3.13__tar.gz → 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/AGENTS.md +77 -16
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/CMakeLists.txt +6 -7
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/PKG-INFO +24 -1
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/README.md +23 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/llms.txt +35 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/pyproject.toml +1 -1
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/advisers.cpp +106 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/bobbin.cpp +81 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/bobbin.h +5 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/common.h +1 -0
- pyopenmagnetics-1.4.0/src/converter.cpp +4199 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/core.cpp +240 -7
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/core.h +10 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/database.cpp +80 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/database.h +5 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/losses.cpp +110 -3
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/losses.h +5 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/plotting.cpp +250 -12
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/plotting.h +5 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/settings.cpp +110 -2
- pyopenmagnetics-1.4.0/src/settings.h +25 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/simulation.cpp +404 -3
- pyopenmagnetics-1.4.0/src/simulation.h +57 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/utils.cpp +289 -3
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/utils.h +12 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/winding.cpp +98 -3
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/winding.h +5 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/wire.cpp +60 -1
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/wire.h +4 -0
- pyopenmagnetics-1.3.13/src/converter.cpp +0 -1460
- pyopenmagnetics-1.3.13/src/settings.h +0 -17
- pyopenmagnetics-1.3.13/src/simulation.h +0 -37
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/.github/workflows/ci.yml +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/.github/workflows/publish.yml +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/.gitignore +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/LICENSE +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/PyOpenMagnetics.pyi +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/api/MAS.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/api/mas_db_reader.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/api/validation.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/clear_cibuildwheel_cache.sh +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/docs/compatibility.md +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/docs/errors.md +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/docs/performance.md +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/README.md +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/buck_inductor.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/complete_simulation_example.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/converter_design_example.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_bobbin.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_coil.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_core.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_plotting.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_220v_12v_1a.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_220v_12v_2a_complete.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_bh_curve.png +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_core.png +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_design.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_summary.png +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_waveforms.png +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/list_plot_funcs.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/plot_flyback_design.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/plot_flyback_pyom.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/test_field_calc.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/test_field_plot.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/force_fresh_build.sh +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/01_getting_started.ipynb +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/02_buck_inductor.ipynb +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/03_core_losses.ipynb +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/README.md +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/requirements.txt +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/advisers.h +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/converter.h +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/logging.cpp +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/logging.h +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/module.cpp +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/test.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/__init__.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/conftest.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_converter_endpoints.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_core.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_core_adviser.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_examples_integration.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_inputs.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_logging.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_magnetic_adviser.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_plotting.py +0 -0
- {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_winding.py +0 -0
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# AGENTS.md — PyOpenMagnetics AI Assistant Guide
|
|
2
2
|
|
|
3
|
+
> **MKF is authoritative for all magnetics math.** Before implementing any
|
|
4
|
+
> magnetics calculation or assuming an API exists, consult
|
|
5
|
+
> [`../MKF/CAPABILITIES.md`](../MKF/CAPABILITIES.md). If a needed capability
|
|
6
|
+
> isn't listed there, ask — don't reinvent it here.
|
|
7
|
+
|
|
8
|
+
> **Two stub files in this repo:**
|
|
9
|
+
> - `PyOpenMagnetics.pyi` — **curated**. Authoritative on arg conventions
|
|
10
|
+
> and gotchas. Read this first.
|
|
11
|
+
> - `PyOpenMagnetics.generated.pyi` — **auto-generated** from the compiled
|
|
12
|
+
> `.so` via pybind11-stubgen. Wider coverage (every exported symbol) but
|
|
13
|
+
> raw — signatures are right, conventions may not be. Use as a discovery
|
|
14
|
+
> index; when it disagrees with the curated stub, trust the curated one.
|
|
15
|
+
|
|
3
16
|
> **This file is the SINGLE SOURCE OF TRUTH for any AI agent using PyOpenMagnetics.**
|
|
4
17
|
> Every instruction was derived from reading the C++ source code
|
|
5
18
|
> (`converter.cpp`, `magnetics.cpp`, `cores.cpp`, `wires.cpp`, `settings.cpp`,
|
|
@@ -615,26 +628,74 @@ subcircuit = PyOM.export_magnetic_as_subcircuit(magnetic)
|
|
|
615
628
|
|
|
616
629
|
## 11. Supported Topologies
|
|
617
630
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
631
|
+
`process_converter("<topology>", json, use_ngspice)` is the universal entry
|
|
632
|
+
point and accepts every string below, plus its `"advanced_<topology>"` form
|
|
633
|
+
(the internal builds the `Advanced*` MKF class either way — "advanced" is
|
|
634
|
+
selected by the JSON payload shape, e.g. presence of `desiredInductance` /
|
|
635
|
+
`desiredMagnetizingInductance` / `desiredBoostInductance`, not by the name).
|
|
636
|
+
|
|
637
|
+
### 11.1 Per-topology API parity matrix
|
|
638
|
+
|
|
639
|
+
Every topology exposes the **same four surfaces** (✓ = present). Columns:
|
|
640
|
+
- **inputs** — `calculate_<t>_inputs(json)` (basic) and
|
|
641
|
+
`calculate_advanced_<t>_inputs(json)` (advanced)
|
|
642
|
+
- **process** — dedicated `process_<t>(json)` thin wrapper (all are also
|
|
643
|
+
reachable via the generic `process_converter`)
|
|
644
|
+
- **simulate** — `simulate_<t>_ideal_waveforms(json)` (ngspice)
|
|
645
|
+
- **ngspice** — `generate_<t>_ngspice_circuit(json, input_voltage_index=0, operating_point_index=0)`
|
|
646
|
+
|
|
647
|
+
| Topology string | inputs (basic / advanced) | process_* | simulate | generate ngspice |
|
|
648
|
+
|---|---|---|---|---|
|
|
649
|
+
| `flyback` | ✓ / ✓ | ✓ | ✓ (+`simulate_flyback_with_magnetic`) | ✓ |
|
|
650
|
+
| `buck` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
651
|
+
| `boost` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
652
|
+
| `single_switch_forward` | ✓ / ✓ | ✓ | ✓ (`simulate_forward_*`) | ✓ (`generate_forward_*`) |
|
|
653
|
+
| `two_switch_forward` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
654
|
+
| `active_clamp_forward` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
655
|
+
| `push_pull` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
656
|
+
| `isolated_buck` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
657
|
+
| `isolated_buck_boost` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
658
|
+
| `cuk` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
659
|
+
| `sepic` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
660
|
+
| `zeta` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
661
|
+
| `four_switch_buck_boost` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
662
|
+
| `weinberg` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
663
|
+
| `llc` | ✓ / ✓ | via `process_converter` | ✓ | ✓ |
|
|
664
|
+
| `cllc` | ✓ / ✓ | via `process_converter` | ✓ | ✓ |
|
|
665
|
+
| `clllc` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
666
|
+
| `src` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
667
|
+
| `dab` | ✓ / ✓ | via `process_converter` | ✓ | ✓ |
|
|
668
|
+
| `phase_shifted_full_bridge` (`psfb`) | ✓ / ✓ | via `process_converter` | ✓ | ✓ |
|
|
669
|
+
| `phase_shifted_half_bridge` (`pshb`) | ✓ / ✓ | via `process_converter` | ✓ | ✓ |
|
|
670
|
+
| `asymmetric_half_bridge` (`ahb`) | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
671
|
+
| `vienna` | ✓ / ✓ | ✓ | ✓ | ✓ |
|
|
672
|
+
| `power_factor_correction` (`pfc`) | ✓ / — ¹ | via `process_converter` | ✓ (`simulate_pfc_waveforms`) | ✓ ² |
|
|
673
|
+
| `current_transformer` | — ³ | ✓ ³ | — | — |
|
|
674
|
+
| `common_mode_choke` (`cmc`) | `calculate_cmc_inputs` / `calculate_advanced_cmc_inputs` | — | `simulate_cmc_ideal_waveforms`, `simulate_cmc_lisn_waveforms` | `generate_cmc_ngspice_circuit` |
|
|
675
|
+
| `differential_mode_choke` (`dmc`) | `calculate_dmc_inputs` | `propose_dmc_design`, `verify_dmc_attenuation` | `simulate_dmc_waveforms` | `generate_dmc_ngspice_circuit` |
|
|
676
|
+
|
|
677
|
+
¹ PFC has no `AdvancedPowerFactorCorrection` class in MKF — basic-only by design;
|
|
678
|
+
there is intentionally no `calculate_advanced_pfc_inputs`.
|
|
679
|
+
² `generate_pfc_ngspice_circuit(json, dc_resistance=0.1, simulation_time=0.02,
|
|
680
|
+
time_step=1e-8)` — PFC is a line-frequency model, so it takes circuit-damping
|
|
681
|
+
parameters instead of the `input_voltage_index` / `operating_point_index`
|
|
682
|
+
sweep indices used by the DC-DC family. Inductance comes from an explicit
|
|
683
|
+
`"inductance"` field or is derived from `"mode"` (CCM/CrCM/DCM).
|
|
684
|
+
³ Current transformer is measurement-only: `process_current_transformer(json,
|
|
685
|
+
turns_ratio, secondary_resistance=0.0)`.
|
|
686
|
+
|
|
687
|
+
### 11.2 Dedicated `process_*` thin wrappers
|
|
688
|
+
|
|
633
689
|
`process_flyback()`, `process_buck()`, `process_boost()`,
|
|
634
690
|
`process_single_switch_forward()`, `process_two_switch_forward()`,
|
|
635
691
|
`process_active_clamp_forward()`, `process_push_pull()`,
|
|
636
692
|
`process_isolated_buck()`, `process_isolated_buck_boost()`,
|
|
637
|
-
`
|
|
693
|
+
`process_cuk()`, `process_sepic()`, `process_zeta()`,
|
|
694
|
+
`process_four_switch_buck_boost()`, `process_asymmetric_half_bridge()`,
|
|
695
|
+
`process_weinberg()`, `process_vienna()`, `process_clllc()`, `process_src()`,
|
|
696
|
+
`process_current_transformer(json, turns_ratio, secondary_resistance=0.0)`.
|
|
697
|
+
Topologies without a dedicated wrapper (`llc`, `cllc`, `dab`, `psfb`, `pshb`,
|
|
698
|
+
`pfc`) are reached through `process_converter("<topology>", json)`.
|
|
638
699
|
|
|
639
700
|
---
|
|
640
701
|
|
|
@@ -24,16 +24,15 @@ else ()
|
|
|
24
24
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-deprecated-declarations -Wno-unused-parameter -Wno-switch")
|
|
25
25
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
26
26
|
|
|
27
|
-
# set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
|
28
27
|
# set(CMAKE_BUILD_TYPE MinSizeRel)
|
|
29
|
-
set(CMAKE_BUILD_TYPE Release)
|
|
30
|
-
|
|
28
|
+
# set(CMAKE_BUILD_TYPE Release)
|
|
29
|
+
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
|
30
|
+
|
|
31
31
|
# Enable Link Time Optimization to reduce binary size
|
|
32
32
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE) # TEMP: disable LTO (OOM)
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
set(
|
|
36
|
-
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--strip-all")
|
|
33
|
+
|
|
34
|
+
# Debug build: keep symbols and frame pointers for gdb backtraces.
|
|
35
|
+
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O1 -g -fno-omit-frame-pointer")
|
|
37
36
|
endif()
|
|
38
37
|
|
|
39
38
|
SET(MAS_DIRECTORY "${CMAKE_BINARY_DIR}/MAS/")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: PyOpenMagnetics
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Python wrapper for OpenMagnetics
|
|
5
5
|
Author-Email: Alfonso Martinez <Alfonso_VII@hotmail.com>
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -314,6 +314,29 @@ magnetics = get_advised_magnetics(inputs, max_results=5)
|
|
|
314
314
|
|----------|-------------|
|
|
315
315
|
| `export_magnetic_as_subcircuit(magnetic, ...)` | Export as SPICE model |
|
|
316
316
|
|
|
317
|
+
### Converter Topologies
|
|
318
|
+
|
|
319
|
+
All 24 power topologies are exposed with a uniform API. Use the generic
|
|
320
|
+
`process_converter("<topology>", converter, use_ngspice)` (also accepts
|
|
321
|
+
`"advanced_<topology>"`), or the per-topology functions below.
|
|
322
|
+
|
|
323
|
+
| Function family | Description |
|
|
324
|
+
|----------|-------------|
|
|
325
|
+
| `process_converter(name, json, use_ngspice=True)` | Universal dispatch for every topology |
|
|
326
|
+
| `design_magnetics_from_converter(name, json, max_results, core_mode, ...)` | Converter → advised magnetic designs (single call) |
|
|
327
|
+
| `calculate_<t>_inputs(json)` | Build MAS inputs (basic mode) for topology `<t>` |
|
|
328
|
+
| `calculate_advanced_<t>_inputs(json)` | Build MAS inputs (advanced mode) |
|
|
329
|
+
| `simulate_<t>_ideal_waveforms(json)` | ngspice ideal-waveform simulation |
|
|
330
|
+
| `generate_<t>_ngspice_circuit(json, input_voltage_index=0, operating_point_index=0)` | Generate ngspice netlist |
|
|
331
|
+
|
|
332
|
+
`<t>` ∈ `flyback, buck, boost, single_switch_forward, two_switch_forward,
|
|
333
|
+
active_clamp_forward, push_pull, isolated_buck, isolated_buck_boost, cuk,
|
|
334
|
+
sepic, zeta, four_switch_buck_boost, weinberg, llc, cllc, clllc, src, dab,
|
|
335
|
+
psfb, pshb, ahb, vienna`. PFC is basic-only (`calculate_pfc_inputs`,
|
|
336
|
+
`generate_pfc_ngspice_circuit(json, dc_resistance=0.1, simulation_time=0.02,
|
|
337
|
+
time_step=1e-8)`); common-/differential-mode chokes use the `cmc` / `dmc`
|
|
338
|
+
families. See `AGENTS.md` §11 for the full per-topology parity matrix.
|
|
339
|
+
|
|
317
340
|
## Core Materials
|
|
318
341
|
|
|
319
342
|
PyOpenMagnetics includes materials from major manufacturers:
|
|
@@ -297,6 +297,29 @@ magnetics = get_advised_magnetics(inputs, max_results=5)
|
|
|
297
297
|
|----------|-------------|
|
|
298
298
|
| `export_magnetic_as_subcircuit(magnetic, ...)` | Export as SPICE model |
|
|
299
299
|
|
|
300
|
+
### Converter Topologies
|
|
301
|
+
|
|
302
|
+
All 24 power topologies are exposed with a uniform API. Use the generic
|
|
303
|
+
`process_converter("<topology>", converter, use_ngspice)` (also accepts
|
|
304
|
+
`"advanced_<topology>"`), or the per-topology functions below.
|
|
305
|
+
|
|
306
|
+
| Function family | Description |
|
|
307
|
+
|----------|-------------|
|
|
308
|
+
| `process_converter(name, json, use_ngspice=True)` | Universal dispatch for every topology |
|
|
309
|
+
| `design_magnetics_from_converter(name, json, max_results, core_mode, ...)` | Converter → advised magnetic designs (single call) |
|
|
310
|
+
| `calculate_<t>_inputs(json)` | Build MAS inputs (basic mode) for topology `<t>` |
|
|
311
|
+
| `calculate_advanced_<t>_inputs(json)` | Build MAS inputs (advanced mode) |
|
|
312
|
+
| `simulate_<t>_ideal_waveforms(json)` | ngspice ideal-waveform simulation |
|
|
313
|
+
| `generate_<t>_ngspice_circuit(json, input_voltage_index=0, operating_point_index=0)` | Generate ngspice netlist |
|
|
314
|
+
|
|
315
|
+
`<t>` ∈ `flyback, buck, boost, single_switch_forward, two_switch_forward,
|
|
316
|
+
active_clamp_forward, push_pull, isolated_buck, isolated_buck_boost, cuk,
|
|
317
|
+
sepic, zeta, four_switch_buck_boost, weinberg, llc, cllc, clllc, src, dab,
|
|
318
|
+
psfb, pshb, ahb, vienna`. PFC is basic-only (`calculate_pfc_inputs`,
|
|
319
|
+
`generate_pfc_ngspice_circuit(json, dc_resistance=0.1, simulation_time=0.02,
|
|
320
|
+
time_step=1e-8)`); common-/differential-mode chokes use the `cmc` / `dmc`
|
|
321
|
+
families. See `AGENTS.md` §11 for the full per-topology parity matrix.
|
|
322
|
+
|
|
300
323
|
## Core Materials
|
|
301
324
|
|
|
302
325
|
PyOpenMagnetics includes materials from major manufacturers:
|
|
@@ -763,6 +763,41 @@ inputs = {
|
|
|
763
763
|
processed = PyOpenMagnetics.process_inputs(inputs)
|
|
764
764
|
```
|
|
765
765
|
|
|
766
|
+
### Low-Level Per-Topology API (uniform across all topologies)
|
|
767
|
+
|
|
768
|
+
Beyond the high-level `process_converter` / `design_magnetics_from_converter`
|
|
769
|
+
entry points, every topology exposes the **same four function families**, so
|
|
770
|
+
any topology can be driven the same way:
|
|
771
|
+
|
|
772
|
+
```python
|
|
773
|
+
# 1. Input builders — basic and advanced modes (advanced = JSON carries a
|
|
774
|
+
# desired* inductance/turns-ratio field; both reach the same MKF engine):
|
|
775
|
+
inputs = PyOpenMagnetics.calculate_dab_inputs(converter)
|
|
776
|
+
inputs_adv = PyOpenMagnetics.calculate_advanced_dab_inputs(converter)
|
|
777
|
+
|
|
778
|
+
# 2. Generic dispatch (accepts "<topology>" and "advanced_<topology>"):
|
|
779
|
+
inputs = PyOpenMagnetics.process_converter("vienna", converter, True)
|
|
780
|
+
|
|
781
|
+
# 3. Ideal-waveform SPICE simulation:
|
|
782
|
+
waveforms = PyOpenMagnetics.simulate_vienna_ideal_waveforms(converter)
|
|
783
|
+
|
|
784
|
+
# 4. ngspice netlist generation:
|
|
785
|
+
netlist = PyOpenMagnetics.generate_vienna_ngspice_circuit(converter, 0, 0)
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
Coverage is uniform for: `flyback, buck, boost, single_switch_forward,
|
|
789
|
+
two_switch_forward, active_clamp_forward, push_pull, isolated_buck,
|
|
790
|
+
isolated_buck_boost, cuk, sepic, zeta, four_switch_buck_boost, weinberg, llc,
|
|
791
|
+
cllc, clllc, src, dab, psfb, pshb, asymmetric_half_bridge (ahb), vienna`.
|
|
792
|
+
Both `calculate_<t>_inputs` and `calculate_advanced_<t>_inputs` exist for each
|
|
793
|
+
of these. Exceptions: **PFC** has no advanced variant
|
|
794
|
+
(`calculate_pfc_inputs` only; `generate_pfc_ngspice_circuit(json,
|
|
795
|
+
dc_resistance=0.1, simulation_time=0.02, time_step=1e-8)` uses a
|
|
796
|
+
line-frequency model with no sweep indices), and **current_transformer** is
|
|
797
|
+
measurement-only (`process_current_transformer`). Common- and
|
|
798
|
+
differential-mode chokes have their own `calculate_cmc_inputs` /
|
|
799
|
+
`calculate_advanced_cmc_inputs` / `calculate_dmc_inputs` families.
|
|
800
|
+
|
|
766
801
|
## Related Projects
|
|
767
802
|
- **MKF**: C++ magnetics engine - github.com/OpenMagnetics/MKF
|
|
768
803
|
- **MAS**: Magnetic Agnostic Structure JSON schema - github.com/OpenMagnetics/MAS
|
|
@@ -236,6 +236,98 @@ json calculate_advised_magnetics_from_cache(json inputsJson, json filterFlowJson
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
json calculate_advised_sections(json masJson, json patternJson, int repetitions) {
|
|
240
|
+
try {
|
|
241
|
+
OpenMagnetics::Mas mas(masJson);
|
|
242
|
+
std::vector<size_t> pattern;
|
|
243
|
+
for (auto& elem : patternJson) {
|
|
244
|
+
pattern.push_back(elem);
|
|
245
|
+
}
|
|
246
|
+
auto bobbin = mas.get_magnetic().get_coil().get_bobbin();
|
|
247
|
+
if (std::holds_alternative<std::string>(bobbin)) {
|
|
248
|
+
auto bobbinString = std::get<std::string>(bobbin);
|
|
249
|
+
if (bobbinString == "Dummy") {
|
|
250
|
+
mas.get_mutable_magnetic().get_mutable_coil().set_bobbin(
|
|
251
|
+
OpenMagnetics::Bobbin::create_quick_bobbin(mas.get_mutable_magnetic().get_mutable_core()));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
for (size_t windingIndex = 0; windingIndex < mas.get_magnetic().get_coil().get_functional_description().size(); ++windingIndex) {
|
|
255
|
+
mas.get_mutable_magnetic().get_mutable_coil().get_mutable_functional_description()[windingIndex].set_wire("Dummy");
|
|
256
|
+
}
|
|
257
|
+
auto sections = OpenMagnetics::CoilAdviser().get_advised_sections(mas, pattern, repetitions);
|
|
258
|
+
json result = json::array();
|
|
259
|
+
for (auto& section : sections) {
|
|
260
|
+
json aux;
|
|
261
|
+
to_json(aux, section);
|
|
262
|
+
result.push_back(aux);
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
catch (const std::exception& exc) {
|
|
267
|
+
return json{{"error", std::string("calculate_advised_sections: ") + exc.what()}};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
json calculate_advised_coil(json masJson) {
|
|
272
|
+
try {
|
|
273
|
+
OpenMagnetics::Settings::GetInstance().set_coil_delimit_and_compact(true);
|
|
274
|
+
OpenMagnetics::Mas mas(masJson);
|
|
275
|
+
for (size_t windingIndex = 0; windingIndex < mas.get_magnetic().get_coil().get_functional_description().size(); ++windingIndex) {
|
|
276
|
+
mas.get_mutable_magnetic().get_mutable_coil().get_mutable_functional_description()[windingIndex].set_wire("Dummy");
|
|
277
|
+
}
|
|
278
|
+
mas.get_mutable_magnetic().get_mutable_coil().set_turns_description(std::nullopt);
|
|
279
|
+
mas.get_mutable_magnetic().get_mutable_coil().set_layers_description(std::nullopt);
|
|
280
|
+
mas.get_mutable_magnetic().get_mutable_coil().set_sections_description(std::nullopt);
|
|
281
|
+
mas.get_mutable_magnetic().get_mutable_coil().set_groups_description(std::nullopt);
|
|
282
|
+
OpenMagnetics::CoilAdviser coilAdviser;
|
|
283
|
+
auto masMagneticsWithCoil = coilAdviser.get_advised_coil(mas, 1);
|
|
284
|
+
if (masMagneticsWithCoil.size() > 0) {
|
|
285
|
+
json result;
|
|
286
|
+
to_json(result, masMagneticsWithCoil[0]);
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
return json{{"error", "No coil found"}};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (const std::exception& exc) {
|
|
294
|
+
return json{{"error", std::string("calculate_advised_coil: ") + exc.what()}};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
json calculate_advised_wires(json windingJson, json sectionJson, json currentJson, json solidInsulationRequirementsJson, double temperature, uint8_t numberSections, size_t maximumNumberResults, bool usePlanarWires) {
|
|
299
|
+
try {
|
|
300
|
+
OpenMagnetics::Settings::GetInstance().set_coil_delimit_and_compact(true);
|
|
301
|
+
OpenMagnetics::Winding winding(windingJson);
|
|
302
|
+
OpenMagnetics::WireSolidInsulationRequirements wireSolidInsulationRequirements(solidInsulationRequirementsJson);
|
|
303
|
+
Section section(sectionJson);
|
|
304
|
+
SignalDescriptor current(currentJson);
|
|
305
|
+
OpenMagnetics::WireAdviser wireAdviser;
|
|
306
|
+
wireAdviser.set_wire_solid_insulation_requirements(wireSolidInsulationRequirements);
|
|
307
|
+
std::vector<std::pair<OpenMagnetics::Winding, double>> windingsWithScoring;
|
|
308
|
+
if (usePlanarWires) {
|
|
309
|
+
windingsWithScoring = wireAdviser.get_advised_planar_wire(winding, section, current, temperature, numberSections, maximumNumberResults);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
windingsWithScoring = wireAdviser.get_advised_wire(winding, section, current, temperature, numberSections, maximumNumberResults);
|
|
313
|
+
}
|
|
314
|
+
json results;
|
|
315
|
+
results["data"] = json::array();
|
|
316
|
+
for (auto& [w, scoring] : windingsWithScoring) {
|
|
317
|
+
json result;
|
|
318
|
+
json windingJson;
|
|
319
|
+
to_json(windingJson, w);
|
|
320
|
+
result["winding"] = windingJson;
|
|
321
|
+
result["scoring"] = scoring;
|
|
322
|
+
results["data"].push_back(result);
|
|
323
|
+
}
|
|
324
|
+
return results;
|
|
325
|
+
}
|
|
326
|
+
catch (const std::exception& exc) {
|
|
327
|
+
return json{{"error", std::string("calculate_advised_wires: ") + exc.what()}};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
239
331
|
void register_adviser_bindings(py::module& m) {
|
|
240
332
|
m.def("calculate_advised_cores", &calculate_advised_cores,
|
|
241
333
|
R"pbdoc(
|
|
@@ -386,6 +478,20 @@ void register_adviser_bindings(py::module& m) {
|
|
|
386
478
|
Returns "Exception: No magnetics found in cache" if cache is empty.
|
|
387
479
|
)pbdoc",
|
|
388
480
|
py::arg("inputs_json"), py::arg("filter_flow_json"), py::arg("max_results"));
|
|
481
|
+
|
|
482
|
+
m.def("calculate_advised_sections", &calculate_advised_sections,
|
|
483
|
+
"Get advised coil sections.",
|
|
484
|
+
py::arg("mas"), py::arg("pattern"), py::arg("repetitions"));
|
|
485
|
+
|
|
486
|
+
m.def("calculate_advised_coil", &calculate_advised_coil,
|
|
487
|
+
"Get full coil design advice.",
|
|
488
|
+
py::arg("mas"));
|
|
489
|
+
|
|
490
|
+
m.def("calculate_advised_wires", &calculate_advised_wires,
|
|
491
|
+
"Get wire selection advice.",
|
|
492
|
+
py::arg("winding"), py::arg("section"), py::arg("current"),
|
|
493
|
+
py::arg("solid_insulation_requirements"), py::arg("temperature"), py::arg("number_sections"),
|
|
494
|
+
py::arg("max_results"), py::arg("use_planar_wires") = false);
|
|
389
495
|
}
|
|
390
496
|
|
|
391
497
|
} // namespace PyMKF
|
|
@@ -99,6 +99,48 @@ bool check_if_fits(json bobbinJson, double dimension, bool isHorizontalOrRadial)
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
json create_simple_bobbin_from_core(json coreJson) {
|
|
103
|
+
try {
|
|
104
|
+
OpenMagnetics::Core core(coreJson, false, false, false);
|
|
105
|
+
auto bobbin = OpenMagnetics::Bobbin::create_quick_bobbin(core);
|
|
106
|
+
|
|
107
|
+
json result;
|
|
108
|
+
to_json(result, bobbin);
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
catch (const std::exception &exc) {
|
|
112
|
+
return "Exception: " + std::string{exc.what()};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
json create_simple_bobbin_from_core_with_custom_thickness(json coreJson, double thickness) {
|
|
117
|
+
try {
|
|
118
|
+
OpenMagnetics::Core core(coreJson, false, false, false);
|
|
119
|
+
auto bobbin = OpenMagnetics::Bobbin::create_quick_bobbin(core, thickness);
|
|
120
|
+
|
|
121
|
+
json result;
|
|
122
|
+
to_json(result, bobbin);
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
catch (const std::exception &exc) {
|
|
126
|
+
return "Exception: " + std::string{exc.what()};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
json create_simple_bobbin_from_core_with_custom_thicknesses(json coreJson, double wallThickness, double columnThickness) {
|
|
131
|
+
try {
|
|
132
|
+
OpenMagnetics::Core core(coreJson, false, false, false);
|
|
133
|
+
auto bobbin = OpenMagnetics::Bobbin::create_quick_bobbin(core, wallThickness, columnThickness);
|
|
134
|
+
|
|
135
|
+
json result;
|
|
136
|
+
to_json(result, bobbin);
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
catch (const std::exception &exc) {
|
|
140
|
+
return "Exception: " + std::string{exc.what()};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
102
144
|
void register_bobbin_bindings(py::module& m) {
|
|
103
145
|
m.def("get_bobbins", &get_bobbins, "Retrieve all available bobbins as JSON objects");
|
|
104
146
|
m.def("get_bobbin_names", &get_bobbin_names, "Retrieve list of all bobbin names");
|
|
@@ -108,6 +150,45 @@ void register_bobbin_bindings(py::module& m) {
|
|
|
108
150
|
m.def("calculate_bobbin_data", &calculate_bobbin_data, "Calculate bobbin specifications");
|
|
109
151
|
m.def("process_bobbin", &process_bobbin, "Process bobbin geometry");
|
|
110
152
|
m.def("check_if_fits", &check_if_fits, "Check if winding fits in available space");
|
|
153
|
+
|
|
154
|
+
m.def("create_simple_bobbin_from_core", &create_simple_bobbin_from_core,
|
|
155
|
+
R"pbdoc(
|
|
156
|
+
Create a simple bobbin from core data.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
core_json: JSON Core object.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
JSON Bobbin object.
|
|
163
|
+
)pbdoc",
|
|
164
|
+
py::arg("core_json"));
|
|
165
|
+
|
|
166
|
+
m.def("create_simple_bobbin_from_core_with_custom_thickness", &create_simple_bobbin_from_core_with_custom_thickness,
|
|
167
|
+
R"pbdoc(
|
|
168
|
+
Create a simple bobbin from core data with custom wall thickness.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
core_json: JSON Core object.
|
|
172
|
+
thickness: Wall thickness in meters.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
JSON Bobbin object.
|
|
176
|
+
)pbdoc",
|
|
177
|
+
py::arg("core_json"), py::arg("thickness"));
|
|
178
|
+
|
|
179
|
+
m.def("create_simple_bobbin_from_core_with_custom_thicknesses", &create_simple_bobbin_from_core_with_custom_thicknesses,
|
|
180
|
+
R"pbdoc(
|
|
181
|
+
Create a simple bobbin from core data with custom wall and column thicknesses.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
core_json: JSON Core object.
|
|
185
|
+
wall_thickness: Wall thickness in meters.
|
|
186
|
+
column_thickness: Column thickness in meters.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
JSON Bobbin object.
|
|
190
|
+
)pbdoc",
|
|
191
|
+
py::arg("core_json"), py::arg("wall_thickness"), py::arg("column_thickness"));
|
|
111
192
|
}
|
|
112
193
|
|
|
113
194
|
} // namespace PyMKF
|
|
@@ -13,6 +13,11 @@ json calculate_bobbin_data(json magneticJson);
|
|
|
13
13
|
json process_bobbin(json bobbinJson);
|
|
14
14
|
bool check_if_fits(json bobbinJson, double dimension, bool isHorizontalOrRadial);
|
|
15
15
|
|
|
16
|
+
// Simple bobbin creation
|
|
17
|
+
json create_simple_bobbin_from_core(json coreJson);
|
|
18
|
+
json create_simple_bobbin_from_core_with_custom_thickness(json coreJson, double thickness);
|
|
19
|
+
json create_simple_bobbin_from_core_with_custom_thicknesses(json coreJson, double wallThickness, double columnThickness);
|
|
20
|
+
|
|
16
21
|
void register_bobbin_bindings(py::module& m);
|
|
17
22
|
|
|
18
23
|
} // namespace PyMKF
|