PyOpenMagnetics 1.3.12__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.12 → pyopenmagnetics-1.4.0}/.github/workflows/publish.yml +16 -11
  2. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/AGENTS.md +77 -16
  3. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/CMakeLists.txt +20 -17
  4. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/PKG-INFO +24 -1
  5. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/README.md +23 -0
  6. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/llms.txt +35 -0
  7. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/pyproject.toml +1 -1
  8. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/advisers.cpp +106 -0
  9. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/bobbin.cpp +81 -0
  10. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/bobbin.h +5 -0
  11. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/common.h +1 -0
  12. pyopenmagnetics-1.4.0/src/converter.cpp +4199 -0
  13. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/core.cpp +240 -7
  14. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/core.h +10 -0
  15. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/database.cpp +80 -0
  16. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/database.h +5 -0
  17. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/losses.cpp +110 -3
  18. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/losses.h +5 -0
  19. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/plotting.cpp +250 -12
  20. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/plotting.h +5 -0
  21. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/settings.cpp +116 -2
  22. pyopenmagnetics-1.4.0/src/settings.h +25 -0
  23. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/simulation.cpp +404 -3
  24. pyopenmagnetics-1.4.0/src/simulation.h +57 -0
  25. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/utils.cpp +289 -3
  26. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/utils.h +12 -0
  27. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/winding.cpp +98 -3
  28. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/winding.h +5 -0
  29. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/wire.cpp +60 -1
  30. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/wire.h +4 -0
  31. pyopenmagnetics-1.3.12/src/converter.cpp +0 -1383
  32. pyopenmagnetics-1.3.12/src/settings.h +0 -17
  33. pyopenmagnetics-1.3.12/src/simulation.h +0 -37
  34. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/.github/workflows/ci.yml +0 -0
  35. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/.gitignore +0 -0
  36. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/LICENSE +0 -0
  37. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/PyOpenMagnetics.pyi +0 -0
  38. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/api/MAS.py +0 -0
  39. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/api/mas_db_reader.py +0 -0
  40. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/api/validation.py +0 -0
  41. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/clear_cibuildwheel_cache.sh +0 -0
  42. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/docs/compatibility.md +0 -0
  43. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/docs/errors.md +0 -0
  44. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/docs/performance.md +0 -0
  45. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/README.md +0 -0
  46. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/buck_inductor.py +0 -0
  47. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/complete_simulation_example.py +0 -0
  48. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/converter_design_example.py +0 -0
  49. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/debug_bobbin.py +0 -0
  50. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/debug_coil.py +0 -0
  51. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/debug_core.py +0 -0
  52. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/debug_plotting.py +0 -0
  53. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_220v_12v_1a.py +0 -0
  54. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_220v_12v_2a_complete.py +0 -0
  55. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_bh_curve.png +0 -0
  56. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_core.png +0 -0
  57. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_design.py +0 -0
  58. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_summary.png +0 -0
  59. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/flyback_waveforms.png +0 -0
  60. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/list_plot_funcs.py +0 -0
  61. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/plot_flyback_design.py +0 -0
  62. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/plot_flyback_pyom.py +0 -0
  63. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/test_field_calc.py +0 -0
  64. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/examples/test_field_plot.py +0 -0
  65. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/force_fresh_build.sh +0 -0
  66. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/notebooks/01_getting_started.ipynb +0 -0
  67. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/notebooks/02_buck_inductor.ipynb +0 -0
  68. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/notebooks/03_core_losses.ipynb +0 -0
  69. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/notebooks/README.md +0 -0
  70. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/requirements.txt +0 -0
  71. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/advisers.h +0 -0
  72. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/converter.h +0 -0
  73. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/logging.cpp +0 -0
  74. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/logging.h +0 -0
  75. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/src/module.cpp +0 -0
  76. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/test.py +0 -0
  77. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/__init__.py +0 -0
  78. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/conftest.py +0 -0
  79. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_converter_endpoints.py +0 -0
  80. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_core.py +0 -0
  81. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_core_adviser.py +0 -0
  82. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_examples_integration.py +0 -0
  83. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_inputs.py +0 -0
  84. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_logging.py +0 -0
  85. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_magnetic_adviser.py +0 -0
  86. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_plotting.py +0 -0
  87. {pyopenmagnetics-1.3.12 → pyopenmagnetics-1.4.0}/tests/test_winding.py +0 -0
@@ -10,6 +10,11 @@ on:
10
10
  required: false
11
11
  default: false
12
12
  type: boolean
13
+ publish_to_pypi:
14
+ description: 'Publish to real PyPI instead of TestPyPI (use to rebuild a failed release without recreating the GitHub release/tag)'
15
+ required: false
16
+ default: false
17
+ type: boolean
13
18
 
14
19
  env:
15
20
  GIT_LFS_SKIP_SMUDGE: 1 # Skip LFS to avoid bandwidth quota issues
@@ -109,18 +114,18 @@ jobs:
109
114
  if [ $i -lt 3 ]; then sleep 60; fi
110
115
  done
111
116
  CIBW_ENVIRONMENT_LINUX: PATH=/opt/rh/gcc-toolset-13/root/usr/bin:$PATH LD_LIBRARY_PATH=/opt/rh/gcc-toolset-13/root/usr/lib64:$LD_LIBRARY_PATH
112
- CIBW_BEFORE_BUILD: pip install --default-timeout=60 --retries 5 scikit-build-core cmake ninja pybind11
117
+ CIBW_BEFORE_BUILD: pip install --default-timeout=60 --retries 5 scikit-build-core "cmake<4" ninja pybind11
113
118
  CIBW_TEST_COMMAND: python -c "import PyOpenMagnetics; print(f'PyOpenMagnetics loaded successfully with {len(dir(PyOpenMagnetics))} functions')"
114
119
 
115
120
  - name: Publish Linux wheels to PyPI
116
- if: github.event_name == 'release'
121
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi)
117
122
  uses: pypa/gh-action-pypi-publish@release/v1
118
123
  with:
119
124
  password: ${{ secrets.PYPI_API_TOKEN }}
120
125
  packages-dir: wheelhouse/
121
126
 
122
127
  - name: Publish Linux wheels to TestPyPI
123
- if: github.event_name == 'workflow_dispatch'
128
+ if: github.event_name == 'workflow_dispatch' && !inputs.publish_to_pypi
124
129
  uses: pypa/gh-action-pypi-publish@release/v1
125
130
  with:
126
131
  repository-url: https://test.pypi.org/legacy/
@@ -181,21 +186,21 @@ jobs:
181
186
  CIBW_BUILD: cp310-* cp311-* cp312-* cp313-*
182
187
  CIBW_SKIP: "*-win32 *-manylinux_i686 *musllinux* pp*"
183
188
  CIBW_BEFORE_ALL_WINDOWS: npm install -g quicktype
184
- CIBW_BEFORE_BUILD: pip install --default-timeout=60 --retries 5 scikit-build-core cmake ninja pybind11
189
+ CIBW_BEFORE_BUILD: pip install --default-timeout=60 --retries 5 scikit-build-core "cmake<4" ninja pybind11
185
190
  CIBW_TEST_COMMAND: python -c "import PyOpenMagnetics; print(f'PyOpenMagnetics loaded successfully with {len(dir(PyOpenMagnetics))} functions')"
186
191
 
187
192
  - name: Install twine
188
193
  run: python -m pip install twine
189
194
 
190
195
  - name: Publish Windows wheels to PyPI
191
- if: github.event_name == 'release'
196
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi)
192
197
  run: python -m twine upload wheelhouse/*.whl
193
198
  env:
194
199
  TWINE_USERNAME: __token__
195
200
  TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
196
201
 
197
202
  - name: Publish Windows wheels to TestPyPI
198
- if: github.event_name == 'workflow_dispatch'
203
+ if: github.event_name == 'workflow_dispatch' && !inputs.publish_to_pypi
199
204
  run: python -m twine upload --repository-url https://test.pypi.org/legacy/ wheelhouse/*.whl
200
205
  env:
201
206
  TWINE_USERNAME: __token__
@@ -266,21 +271,21 @@ jobs:
266
271
  if [ $i -lt 5 ]; then sleep 60; fi
267
272
  done
268
273
  CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=15.0
269
- CIBW_BEFORE_BUILD: pip install --default-timeout=60 --retries 5 scikit-build-core cmake ninja pybind11
274
+ CIBW_BEFORE_BUILD: pip install --default-timeout=60 --retries 5 scikit-build-core "cmake<4" ninja pybind11
270
275
  CIBW_TEST_COMMAND: python -c "import PyOpenMagnetics; print(f'PyOpenMagnetics loaded successfully with {len(dir(PyOpenMagnetics))} functions')"
271
276
 
272
277
  - name: Install twine
273
278
  run: python -m pip install twine
274
279
 
275
280
  - name: Publish macOS wheels to PyPI
276
- if: github.event_name == 'release'
281
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi)
277
282
  run: python -m twine upload wheelhouse/*.whl
278
283
  env:
279
284
  TWINE_USERNAME: __token__
280
285
  TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
281
286
 
282
287
  - name: Publish macOS wheels to TestPyPI
283
- if: github.event_name == 'workflow_dispatch'
288
+ if: github.event_name == 'workflow_dispatch' && !inputs.publish_to_pypi
284
289
  run: python -m twine upload --repository-url https://test.pypi.org/legacy/ wheelhouse/*.whl
285
290
  env:
286
291
  TWINE_USERNAME: __token__
@@ -338,14 +343,14 @@ jobs:
338
343
  run: python -m build --sdist
339
344
 
340
345
  - name: Publish sdist to PyPI
341
- if: github.event_name == 'release'
346
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi)
342
347
  uses: pypa/gh-action-pypi-publish@release/v1
343
348
  with:
344
349
  password: ${{ secrets.PYPI_API_TOKEN }}
345
350
  packages-dir: dist/
346
351
 
347
352
  - name: Publish sdist to TestPyPI
348
- if: github.event_name == 'workflow_dispatch'
353
+ if: github.event_name == 'workflow_dispatch' && !inputs.publish_to_pypi
349
354
  uses: pypa/gh-action-pypi-publish@release/v1
350
355
  with:
351
356
  repository-url: https://test.pypi.org/legacy/
@@ -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/")
@@ -123,12 +122,12 @@ if(NOT LOCAL_MKF_MAS)
123
122
  set(MKF_FORCE_REFRESH "2026-04-29-extra-components")
124
123
  # Tell MKF to disable matplotplusplus and use SVG-based Painter instead
125
124
  set(INCLUDE_PYMKF ON CACHE BOOL "Build Python interface" FORCE)
126
- # GIT_SUBMODULES_RECURSE pulls in CAS/EAS (added 2026-04 alongside the
125
+ # GIT_SUBMODULES_RECURSE pulls in CAS/PEAS (added 2026-04 alongside the
127
126
  # ExtraComponentsMode API). MAS is also a submodule of MKF but PyMKF
128
- # fetches it independently below for fast-update reasons; CAS/EAS only
127
+ # fetches it independently below for fast-update reasons; CAS/PEAS only
129
128
  # exist as MKF submodules, so we need them populated under MKF/.
130
129
  # NOTE: we cannot use GIT_SHALLOW with GIT_SUBMODULES — shallow clone
131
- # skips submodule init. Drop the shallow flag for MKF so CAS/EAS/
130
+ # skips submodule init. Drop the shallow flag for MKF so CAS/PEAS/
132
131
  # cci_coords are actually checked out. cci_coords MUST stay in this
133
132
  # list — the CCI generator reads from MKF/cci_coords/coordinates/.
134
133
  # MAS is fetched separately below (not a sub-fetch of MKF here) so
@@ -137,7 +136,7 @@ if(NOT LOCAL_MKF_MAS)
137
136
  GIT_REPOSITORY https://github.com/OpenMagnetics/MKF.git
138
137
  GIT_TAG main
139
138
  GIT_PROGRESS TRUE
140
- GIT_SUBMODULES "CAS" "EAS" "cci_coords"
139
+ GIT_SUBMODULES "CAS" "PEAS" "cci_coords"
141
140
  GIT_SUBMODULES_RECURSE TRUE)
142
141
 
143
142
  message(STATUS "Fetching mas")
@@ -262,14 +261,14 @@ add_custom_target(PyMASGeneration
262
261
 
263
262
  # ──────────────────────────────────────────────────────────────────
264
263
  # CAS.hpp generation (mirrors MKF/CMakeLists.txt:419-451)
265
- # CAS = Capacitor Adviser Schema. EAS = Element Adviser Schema.
264
+ # CAS = Capacitor Adviser Schema. PEAS = Power Element Adviser Schema.
266
265
  # Both are submodules of MKF (added 2026-04). MKF/Topology.h #includes
267
266
  # <CAS.hpp> for the get_extra_components_inputs API; we must generate
268
267
  # the header here so PyOpenMagnetics's TU sees it.
269
268
  # ──────────────────────────────────────────────────────────────────
270
269
  set(CAS_DIRECTORY "${CMAKE_BINARY_DIR}/CAS/")
271
270
  set(CAS_DIR "${MKF_DIR}/CAS")
272
- set(EAS_DIR "${MKF_DIR}/EAS")
271
+ set(PEAS_DIR "${MKF_DIR}/PEAS")
273
272
  file(MAKE_DIRECTORY "${CAS_DIRECTORY}")
274
273
 
275
274
  add_custom_command(
@@ -277,8 +276,10 @@ add_custom_command(
277
276
  COMMAND ${CMAKE_COMMAND} -E remove -f "${CAS_DIRECTORY}/CAS.hpp"
278
277
  COMMAND quicktype -l c++ -s schema ${CAS_DIR}/schemas/inputs.json
279
278
  -S ${CAS_DIR}/schemas/inputs/designRequirements.json
280
- -S ${EAS_DIR}/schemas/utils.json
281
- -S ${EAS_DIR}/schemas/inputs/twoTerminalOperatingPoint.json
279
+ -S ${PEAS_DIR}/schemas/utils.json
280
+ -S ${PEAS_DIR}/schemas/inputs/twoTerminalOperatingPoint.json
281
+ -S ${PEAS_DIR}/schemas/inputs/operatingConditions.json
282
+ -S ${PEAS_DIR}/schemas/inputs/operatingPointExcitation.json
282
283
  -o ${CAS_DIRECTORY}/CAS.hpp --namespace CAS --source-style single-source
283
284
  --type-style pascal-case --member-style underscore-case
284
285
  --enumerator-style upper-underscore-case --no-boost
@@ -286,8 +287,10 @@ add_custom_command(
286
287
  DEPENDS
287
288
  "${CAS_DIR}/schemas/inputs.json"
288
289
  "${CAS_DIR}/schemas/inputs/designRequirements.json"
289
- "${EAS_DIR}/schemas/utils.json"
290
- "${EAS_DIR}/schemas/inputs/twoTerminalOperatingPoint.json"
290
+ "${PEAS_DIR}/schemas/utils.json"
291
+ "${PEAS_DIR}/schemas/inputs/twoTerminalOperatingPoint.json"
292
+ "${PEAS_DIR}/schemas/inputs/operatingConditions.json"
293
+ "${PEAS_DIR}/schemas/inputs/operatingPointExcitation.json"
291
294
  USES_TERMINAL)
292
295
 
293
296
  add_custom_target(PyCASGeneration
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: PyOpenMagnetics
3
- Version: 1.3.12
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.12"
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