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.
Files changed (87) hide show
  1. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/AGENTS.md +77 -16
  2. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/CMakeLists.txt +6 -7
  3. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/PKG-INFO +24 -1
  4. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/README.md +23 -0
  5. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/llms.txt +35 -0
  6. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/pyproject.toml +1 -1
  7. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/advisers.cpp +106 -0
  8. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/bobbin.cpp +81 -0
  9. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/bobbin.h +5 -0
  10. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/common.h +1 -0
  11. pyopenmagnetics-1.4.0/src/converter.cpp +4199 -0
  12. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/core.cpp +240 -7
  13. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/core.h +10 -0
  14. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/database.cpp +80 -0
  15. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/database.h +5 -0
  16. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/losses.cpp +110 -3
  17. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/losses.h +5 -0
  18. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/plotting.cpp +250 -12
  19. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/plotting.h +5 -0
  20. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/settings.cpp +110 -2
  21. pyopenmagnetics-1.4.0/src/settings.h +25 -0
  22. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/simulation.cpp +404 -3
  23. pyopenmagnetics-1.4.0/src/simulation.h +57 -0
  24. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/utils.cpp +289 -3
  25. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/utils.h +12 -0
  26. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/winding.cpp +98 -3
  27. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/winding.h +5 -0
  28. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/wire.cpp +60 -1
  29. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/wire.h +4 -0
  30. pyopenmagnetics-1.3.13/src/converter.cpp +0 -1460
  31. pyopenmagnetics-1.3.13/src/settings.h +0 -17
  32. pyopenmagnetics-1.3.13/src/simulation.h +0 -37
  33. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/.github/workflows/ci.yml +0 -0
  34. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/.github/workflows/publish.yml +0 -0
  35. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/.gitignore +0 -0
  36. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/LICENSE +0 -0
  37. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/PyOpenMagnetics.pyi +0 -0
  38. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/api/MAS.py +0 -0
  39. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/api/mas_db_reader.py +0 -0
  40. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/api/validation.py +0 -0
  41. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/clear_cibuildwheel_cache.sh +0 -0
  42. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/docs/compatibility.md +0 -0
  43. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/docs/errors.md +0 -0
  44. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/docs/performance.md +0 -0
  45. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/README.md +0 -0
  46. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/buck_inductor.py +0 -0
  47. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/complete_simulation_example.py +0 -0
  48. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/converter_design_example.py +0 -0
  49. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_bobbin.py +0 -0
  50. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_coil.py +0 -0
  51. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_core.py +0 -0
  52. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/debug_plotting.py +0 -0
  53. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_220v_12v_1a.py +0 -0
  54. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_220v_12v_2a_complete.py +0 -0
  55. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_bh_curve.png +0 -0
  56. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_core.png +0 -0
  57. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_design.py +0 -0
  58. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_summary.png +0 -0
  59. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/flyback_waveforms.png +0 -0
  60. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/list_plot_funcs.py +0 -0
  61. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/plot_flyback_design.py +0 -0
  62. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/plot_flyback_pyom.py +0 -0
  63. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/test_field_calc.py +0 -0
  64. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/examples/test_field_plot.py +0 -0
  65. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/force_fresh_build.sh +0 -0
  66. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/01_getting_started.ipynb +0 -0
  67. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/02_buck_inductor.ipynb +0 -0
  68. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/03_core_losses.ipynb +0 -0
  69. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/notebooks/README.md +0 -0
  70. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/requirements.txt +0 -0
  71. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/advisers.h +0 -0
  72. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/converter.h +0 -0
  73. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/logging.cpp +0 -0
  74. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/logging.h +0 -0
  75. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/src/module.cpp +0 -0
  76. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/test.py +0 -0
  77. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/__init__.py +0 -0
  78. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/conftest.py +0 -0
  79. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_converter_endpoints.py +0 -0
  80. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_core.py +0 -0
  81. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_core_adviser.py +0 -0
  82. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_examples_integration.py +0 -0
  83. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_inputs.py +0 -0
  84. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_logging.py +0 -0
  85. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_magnetic_adviser.py +0 -0
  86. {pyopenmagnetics-1.3.13 → pyopenmagnetics-1.4.0}/tests/test_plotting.py +0 -0
  87. {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
- | Topology string | Method A class | Singular/Plural | Notes |
619
- |---|---|---|---|
620
- | `"flyback"` | `Flyback` | PLURAL + **mode required** | Most common |
621
- | `"buck"` | `Buck` | **SINGULAR** | |
622
- | `"boost"` | `Boost` | **SINGULAR** | |
623
- | `"single_switch_forward"` | `SingleSwitchForward` | PLURAL | switchingFreq REQUIRED |
624
- | `"two_switch_forward"` | `TwoSwitchForward` | PLURAL | switchingFreq REQUIRED |
625
- | `"active_clamp_forward"` | `ActiveClampForward` | PLURAL | switchingFreq REQUIRED |
626
- | `"push_pull"` | `PushPull` | PLURAL | Same as Forward |
627
- | `"llc"` | `Llc` | PLURAL | |
628
- | `"isolated_buck"` | `IsolatedBuck` | PLURAL | |
629
- | `"isolated_buck_boost"` | `IsolatedBuckBoost` | PLURAL | |
630
- | Others (`"cllc"`, `"dab"`, `"psfb"`, `"pshb"`) | internal fallback | varies | |
631
-
632
- Per-topology thin wrappers for `process_converter`:
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
- `process_current_transformer(json, turns_ratio, secondary_resistance=0.0)`
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
- # Strip symbols and use size optimization
35
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s -Os")
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.13
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
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "PyOpenMagnetics"
7
- version = "1.3.13"
7
+ version = "1.4.0"
8
8
  requires-python = ">=3.8"
9
9
  authors = [
10
10
  { name="Alfonso Martinez", email="Alfonso_VII@hotmail.com" },
@@ -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
@@ -35,6 +35,7 @@
35
35
  #include "processors/MagneticSimulator.h"
36
36
  #include "processors/CircuitSimulatorInterface.h"
37
37
  #include "processors/NgspiceRunner.h"
38
+ #include "processors/Sweeper.h"
38
39
  #include "support/Painter.h"
39
40
  #include "support/Utils.h"
40
41