PyOpenMagnetics 1.6.3__tar.gz → 1.6.4__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 (89) hide show
  1. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/.github/workflows/ci.yml +106 -90
  2. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/CMakeLists.txt +14 -1
  3. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/PKG-INFO +1 -1
  4. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/pyproject.toml +1 -1
  5. pyopenmagnetics-1.6.4/src/crossref.cpp +164 -0
  6. pyopenmagnetics-1.6.4/src/crossref.h +20 -0
  7. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/losses.cpp +11 -5
  8. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/module.cpp +2 -0
  9. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/.github/workflows/publish.yml +0 -0
  10. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/.gitignore +0 -0
  11. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/AGENTS.md +0 -0
  12. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/LICENSE +0 -0
  13. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/PyOpenMagnetics.pyi +0 -0
  14. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/README.md +0 -0
  15. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/__init__.py +0 -0
  16. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/api/MAS.py +0 -0
  17. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/api/mas_db_reader.py +0 -0
  18. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/api/validation.py +0 -0
  19. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/clear_cibuildwheel_cache.sh +0 -0
  20. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/docs/compatibility.md +0 -0
  21. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/docs/errors.md +0 -0
  22. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/docs/performance.md +0 -0
  23. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/README.md +0 -0
  24. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/buck_inductor.py +0 -0
  25. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/complete_simulation_example.py +0 -0
  26. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/converter_design_example.py +0 -0
  27. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/debug_bobbin.py +0 -0
  28. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/debug_coil.py +0 -0
  29. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/debug_core.py +0 -0
  30. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/debug_plotting.py +0 -0
  31. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_220v_12v_1a.py +0 -0
  32. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_220v_12v_2a_complete.py +0 -0
  33. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_bh_curve.png +0 -0
  34. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_core.png +0 -0
  35. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_design.py +0 -0
  36. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_summary.png +0 -0
  37. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/flyback_waveforms.png +0 -0
  38. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/list_plot_funcs.py +0 -0
  39. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/plot_flyback_design.py +0 -0
  40. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/plot_flyback_pyom.py +0 -0
  41. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/test_field_calc.py +0 -0
  42. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/examples/test_field_plot.py +0 -0
  43. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/force_fresh_build.sh +0 -0
  44. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/llms.txt +0 -0
  45. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/notebooks/01_getting_started.ipynb +0 -0
  46. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/notebooks/02_buck_inductor.ipynb +0 -0
  47. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/notebooks/03_core_losses.ipynb +0 -0
  48. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/notebooks/README.md +0 -0
  49. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/requirements.txt +0 -0
  50. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/advisers.cpp +0 -0
  51. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/advisers.h +0 -0
  52. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/bobbin.cpp +0 -0
  53. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/bobbin.h +0 -0
  54. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/cmc.cpp +0 -0
  55. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/cmc.h +0 -0
  56. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/common.h +0 -0
  57. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/converter.cpp +0 -0
  58. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/converter.h +0 -0
  59. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/core.cpp +0 -0
  60. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/core.h +0 -0
  61. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/database.cpp +0 -0
  62. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/database.h +0 -0
  63. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/logging.cpp +0 -0
  64. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/logging.h +0 -0
  65. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/losses.h +0 -0
  66. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/plotting.cpp +0 -0
  67. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/plotting.h +0 -0
  68. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/settings.cpp +0 -0
  69. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/settings.h +0 -0
  70. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/simulation.cpp +0 -0
  71. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/simulation.h +0 -0
  72. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/utils.cpp +0 -0
  73. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/utils.h +0 -0
  74. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/winding.cpp +0 -0
  75. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/winding.h +0 -0
  76. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/wire.cpp +0 -0
  77. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/src/wire.h +0 -0
  78. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/test.py +0 -0
  79. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/__init__.py +0 -0
  80. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/conftest.py +0 -0
  81. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_converter_endpoints.py +0 -0
  82. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_core.py +0 -0
  83. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_core_adviser.py +0 -0
  84. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_examples_integration.py +0 -0
  85. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_inputs.py +0 -0
  86. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_logging.py +0 -0
  87. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_magnetic_adviser.py +0 -0
  88. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_plotting.py +0 -0
  89. {pyopenmagnetics-1.6.3 → pyopenmagnetics-1.6.4}/tests/test_winding.py +0 -0
@@ -1,90 +1,106 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [main, master, develop]
6
- pull_request:
7
- branches: [main, master, develop]
8
-
9
- env:
10
- GIT_LFS_SKIP_SMUDGE: 1 # Skip LFS to avoid bandwidth quota issues
11
-
12
- jobs:
13
- test:
14
- name: Test on ${{ matrix.os }} / Python ${{ matrix.python-version }}
15
- runs-on: ${{ matrix.os }}
16
- strategy:
17
- fail-fast: false
18
- matrix:
19
- os: [ubuntu-22.04, windows-2022, macos-14]
20
- python-version: ["3.10", "3.11", "3.12"]
21
-
22
- steps:
23
- - uses: actions/checkout@v4
24
- with:
25
- submodules: recursive
26
-
27
- - name: Set up Python ${{ matrix.python-version }}
28
- uses: actions/setup-python@v5
29
- with:
30
- python-version: ${{ matrix.python-version }}
31
-
32
- - name: Set up Node.js
33
- uses: actions/setup-node@v4
34
- with:
35
- node-version: "18"
36
-
37
- - name: Install quicktype
38
- run: npm install -g quicktype
39
-
40
- - name: Install build dependencies
41
- run: |
42
- python -m pip install --upgrade pip
43
- pip install build pytest
44
-
45
- - name: Build and install package
46
- run: |
47
- pip install .
48
-
49
- - name: Verify installation
50
- run: |
51
- python -c "import PyOpenMagnetics; print('PyOpenMagnetics loaded with', len(dir(PyOpenMagnetics)), 'functions')"
52
-
53
- - name: Run tests
54
- run: |
55
- pytest tests/ -v --tb=short
56
- continue-on-error: true # Some tests may require specific data files
57
-
58
- build_check:
59
- name: Build check
60
- runs-on: ubuntu-22.04
61
- steps:
62
- - uses: actions/checkout@v4
63
- with:
64
- submodules: recursive
65
-
66
- - name: Set up Python
67
- uses: actions/setup-python@v5
68
- with:
69
- python-version: "3.11"
70
-
71
- - name: Set up Node.js
72
- uses: actions/setup-node@v4
73
- with:
74
- node-version: "18"
75
-
76
- - name: Install quicktype
77
- run: npm install -g quicktype
78
-
79
- - name: Install build
80
- run: python -m pip install build
81
-
82
- - name: Build package
83
- run: python -m build
84
-
85
- - name: Check built files
86
- run: |
87
- ls -la dist/
88
- echo "--- Wheel contents ---"
89
- python -m zipfile -l dist/*.whl | head -50
90
-
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master, develop]
6
+ pull_request:
7
+ branches: [main, master, develop]
8
+
9
+ env:
10
+ GIT_LFS_SKIP_SMUDGE: 1 # Skip LFS to avoid bandwidth quota issues
11
+
12
+ jobs:
13
+ test:
14
+ name: Test on ${{ matrix.os }} / Python ${{ matrix.python-version }}
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [ubuntu-22.04, windows-2022, macos-14]
20
+ python-version: ["3.10", "3.11", "3.12"]
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ submodules: recursive
26
+
27
+ - name: Set up Python ${{ matrix.python-version }}
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+
32
+ - name: Set up Node.js
33
+ uses: actions/setup-node@v4
34
+ with:
35
+ node-version: "18"
36
+
37
+ - name: Rewrite SSH submodule URLs to HTTPS
38
+ # Kirchhoff (fetched at build time by CMake ExternalProject) declares its
39
+ # PSMA schema submodules with git@github.com: URLs, which a runner cannot
40
+ # authenticate -> "Permission denied (publickey)" and a failed wheel build.
41
+ # publish.yml already does this inside CIBW_BEFORE_ALL_*; CI never did,
42
+ # which is why every CI job was red on every OS while publish stayed green.
43
+ run: git config --global url."https://github.com/".insteadOf "git@github.com:"
44
+
45
+ - name: Install quicktype
46
+ run: npm install -g quicktype@23.2.6
47
+
48
+ - name: Install build dependencies
49
+ run: |
50
+ python -m pip install --upgrade pip
51
+ pip install build pytest
52
+
53
+ - name: Build and install package
54
+ run: |
55
+ pip install .
56
+
57
+ - name: Verify installation
58
+ run: |
59
+ python -c "import PyOpenMagnetics; print('PyOpenMagnetics loaded with', len(dir(PyOpenMagnetics)), 'functions')"
60
+
61
+ - name: Run tests
62
+ run: |
63
+ pytest tests/ -v --tb=short
64
+ continue-on-error: true # Some tests may require specific data files
65
+
66
+ build_check:
67
+ name: Build check
68
+ runs-on: ubuntu-22.04
69
+ steps:
70
+ - uses: actions/checkout@v4
71
+ with:
72
+ submodules: recursive
73
+
74
+ - name: Set up Python
75
+ uses: actions/setup-python@v5
76
+ with:
77
+ python-version: "3.11"
78
+
79
+ - name: Set up Node.js
80
+ uses: actions/setup-node@v4
81
+ with:
82
+ node-version: "18"
83
+
84
+ - name: Rewrite SSH submodule URLs to HTTPS
85
+ # Kirchhoff (fetched at build time by CMake ExternalProject) declares its
86
+ # PSMA schema submodules with git@github.com: URLs, which a runner cannot
87
+ # authenticate -> "Permission denied (publickey)" and a failed wheel build.
88
+ # publish.yml already does this inside CIBW_BEFORE_ALL_*; CI never did,
89
+ # which is why every CI job was red on every OS while publish stayed green.
90
+ run: git config --global url."https://github.com/".insteadOf "git@github.com:"
91
+
92
+ - name: Install quicktype
93
+ run: npm install -g quicktype@23.2.6
94
+
95
+ - name: Install build
96
+ run: python -m pip install build
97
+
98
+ - name: Build package
99
+ run: python -m build
100
+
101
+ - name: Check built files
102
+ run: |
103
+ ls -la dist/
104
+ echo "--- Wheel contents ---"
105
+ python -m zipfile -l dist/*.whl | head -50
106
+
@@ -142,7 +142,7 @@ if(NOT LOCAL_MKF_MAS)
142
142
  set(MKF_GIT_TAG "main"
143
143
  CACHE STRING "MKF git ref for the vendored PyOM build")
144
144
  # Force fresh clone by using a unique timestamp - update this when the pin changes
145
- set(MKF_FORCE_REFRESH "2026-07-09-cm-sweep-permeability-poco")
145
+ set(MKF_FORCE_REFRESH "2026-08-05-v1.6.4-mkf-dragback-adviser-thermal")
146
146
  # Tell MKF to disable matplotplusplus and use SVG-based Painter instead
147
147
  set(INCLUDE_PYMKF ON CACHE BOOL "Build Python interface" FORCE)
148
148
  # GIT_SUBMODULES_RECURSE pulls in CAS/PEAS (added 2026-04 alongside the
@@ -243,6 +243,10 @@ endif()
243
243
  message(STATUS "Compiling MAS")
244
244
 
245
245
 
246
+ # Every schema the generated header is built from — the DEPENDS list below.
247
+ file(GLOB_RECURSE MAS_SCHEMA_FILES CONFIGURE_DEPENDS "${MAS_DIR}/schemas/*.json")
248
+ file(GLOB_RECURSE PEAS_SCHEMA_FILES CONFIGURE_DEPENDS "${MKF_DIR}/PEAS/schemas/*.json")
249
+
246
250
  add_custom_command(
247
251
  OUTPUT "${MAS_DIRECTORY}/MAS.hpp"
248
252
  # Force regeneration by removing output first
@@ -321,6 +325,15 @@ add_custom_command(
321
325
  -S ${MAS_DIR}/schemas/inputs/topologies/seriesResonant.json
322
326
  -S ${MAS_DIR}/schemas/inputs/topologies/vienna.json
323
327
  -o ${MAS_DIRECTORY}/MAS.hpp --namespace MAS --source-style single-source --type-style pascal-case --member-style underscore-case --enumerator-style upper-underscore-case --no-boost
328
+ # WITHOUT THIS, CMake treats MAS.hpp as up to date forever once the file
329
+ # exists: no dependency is declared, so the schemas can change and the header
330
+ # silently keeps stale members. That is how a 6 July MAS.hpp survived a 28 July
331
+ # schema and broke MKF's Coil.h on Winding::set_winding_window — the schema had
332
+ # `windingWindow`, the generated class did not. (The `remove -f` above does NOT
333
+ # help: it runs only once CMake has already decided to regenerate.)
334
+ # Globbed rather than repeating the ~80-entry -S list, which would drift out of
335
+ # sync with it; CONFIGURE_DEPENDS also re-globs when a schema file is added.
336
+ DEPENDS ${MAS_SCHEMA_FILES} ${PEAS_SCHEMA_FILES}
324
337
  USES_TERMINAL)
325
338
 
326
339
  add_custom_target(PyMASGeneration
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: PyOpenMagnetics
3
- Version: 1.6.3
3
+ Version: 1.6.4
4
4
  Summary: Python wrapper for OpenMagnetics
5
5
  Author-Email: Alfonso Martinez <Alfonso_VII@hotmail.com>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "PyOpenMagnetics"
7
- version = "1.6.3"
7
+ version = "1.6.4"
8
8
  requires-python = ">=3.8"
9
9
  authors = [
10
10
  { name="Alfonso Martinez", email="Alfonso_VII@hotmail.com" },
@@ -0,0 +1,164 @@
1
+ #include "crossref.h"
2
+
3
+ #include "advisers/CoreCrossReferencer.h"
4
+ #include "advisers/CoreMaterialCrossReferencer.h"
5
+
6
+ namespace PyMKF {
7
+
8
+ // The cross-referencers were reachable only from the WASM build (the web app's
9
+ // `crossReferencers` module), so a Python consumer could not offer the
10
+ // CoreCrossReferencer / CoreMaterialCrossReferencer tools the app has. These
11
+ // mirror that surface, following the same {"data": ...} envelope and
12
+ // "Exception: ..." error convention as the advisers.
13
+
14
+ json calculate_cross_referenced_core(json referenceCoreJson, json inputsJson,
15
+ int64_t referenceNumberTurns, json weightsJson,
16
+ int maximumNumberResults) {
17
+ try {
18
+ OpenMagnetics::Core referenceCore(referenceCoreJson);
19
+ OpenMagnetics::Inputs inputs(inputsJson);
20
+
21
+ std::map<std::string, double> weightsKeysJson = weightsJson;
22
+ std::map<OpenMagnetics::CoreCrossReferencerFilters, double> weights;
23
+ for (auto const& [filterName, weight] : weightsKeysJson) {
24
+ OpenMagnetics::CoreCrossReferencerFilters filter;
25
+ OpenMagnetics::from_json(filterName, filter);
26
+ weights[filter] = weight;
27
+ }
28
+
29
+ OpenMagnetics::CoreCrossReferencer coreCrossReferencer;
30
+ auto scoredCores = weights.empty()
31
+ ? coreCrossReferencer.get_cross_referenced_core(referenceCore, referenceNumberTurns,
32
+ inputs, maximumNumberResults)
33
+ : coreCrossReferencer.get_cross_referenced_core(referenceCore, referenceNumberTurns,
34
+ inputs, weights, maximumNumberResults);
35
+
36
+ auto scoringsPerFilter = coreCrossReferencer.get_scorings();
37
+
38
+ json results = json();
39
+ results["data"] = json::array();
40
+ for (auto& [core, scoring] : scoredCores) {
41
+ json result;
42
+ json coreJson;
43
+ to_json(coreJson, core);
44
+ result["core"] = coreJson;
45
+ result["scoring"] = scoring;
46
+
47
+ std::string name = core.get_name().value_or("");
48
+ if (scoringsPerFilter.count(name)) {
49
+ json filterScorings;
50
+ for (auto& [filter, filterScore] : scoringsPerFilter[name]) {
51
+ filterScorings[std::string(magic_enum::enum_name(filter))] = filterScore;
52
+ }
53
+ result["scoringPerFilter"] = filterScorings;
54
+ }
55
+ results["data"].push_back(result);
56
+ }
57
+
58
+ OpenMagnetics::settings.reset();
59
+ return results;
60
+ }
61
+ catch (const std::exception &exc) {
62
+ json exception;
63
+ exception["data"] = "Exception: " + std::string{exc.what()};
64
+ return exception;
65
+ }
66
+ }
67
+
68
+ json calculate_cross_referenced_core_material(json referenceCoreMaterialJson, double temperature,
69
+ json weightsJson, int maximumNumberResults) {
70
+ try {
71
+ CoreMaterial referenceCoreMaterial(referenceCoreMaterialJson);
72
+
73
+ std::map<std::string, double> weightsKeysJson = weightsJson;
74
+ std::map<OpenMagnetics::CoreMaterialCrossReferencerFilters,
75
+ double> weights;
76
+ for (auto const& [filterName, weight] : weightsKeysJson) {
77
+ OpenMagnetics::CoreMaterialCrossReferencerFilters filter;
78
+ OpenMagnetics::from_json(filterName, filter);
79
+ weights[filter] = weight;
80
+ }
81
+
82
+ OpenMagnetics::CoreMaterialCrossReferencer coreMaterialCrossReferencer;
83
+ auto scoredMaterials = weights.empty()
84
+ ? coreMaterialCrossReferencer.get_cross_referenced_core_material(
85
+ referenceCoreMaterial, temperature, maximumNumberResults)
86
+ : coreMaterialCrossReferencer.get_cross_referenced_core_material(
87
+ referenceCoreMaterial, temperature, weights, maximumNumberResults);
88
+
89
+ auto scoringsPerFilter = coreMaterialCrossReferencer.get_scorings();
90
+
91
+ json results = json();
92
+ results["data"] = json::array();
93
+ for (auto& [material, scoring] : scoredMaterials) {
94
+ json result;
95
+ json materialJson;
96
+ to_json(materialJson, material);
97
+ result["material"] = materialJson;
98
+ result["scoring"] = scoring;
99
+
100
+ std::string name = material.get_name();
101
+ if (scoringsPerFilter.count(name)) {
102
+ json filterScorings;
103
+ for (auto& [filter, filterScore] : scoringsPerFilter[name]) {
104
+ filterScorings[std::string(magic_enum::enum_name(filter))] = filterScore;
105
+ }
106
+ result["scoringPerFilter"] = filterScorings;
107
+ }
108
+ results["data"].push_back(result);
109
+ }
110
+
111
+ OpenMagnetics::settings.reset();
112
+ return results;
113
+ }
114
+ catch (const std::exception &exc) {
115
+ json exception;
116
+ exception["data"] = "Exception: " + std::string{exc.what()};
117
+ return exception;
118
+ }
119
+ }
120
+
121
+ void register_crossref_bindings(py::module& m) {
122
+ m.def("calculate_cross_referenced_core", &calculate_cross_referenced_core,
123
+ R"pbdoc(
124
+ Rank cores that could replace a reference core.
125
+
126
+ Args:
127
+ reference_core_json: the core being replaced (shape, material, gapping).
128
+ inputs_json: design requirements and operating points the replacement must meet.
129
+ reference_number_turns: turns on the reference design.
130
+ weights_json: optional filter weights. Keys: "PERMEANCE", "CORE_LOSSES",
131
+ "SATURATION", "WINDING_WINDOW_AREA", "EFFECTIVE_AREA",
132
+ "ENVELOPING_VOLUME". Empty uses the adviser's defaults.
133
+ max_results: how many alternatives to return.
134
+
135
+ Returns:
136
+ {"data": [{"core", "scoring", "scoringPerFilter"}]} best first, or
137
+ {"data": "Exception: ..."} on failure.
138
+ )pbdoc",
139
+ py::arg("reference_core_json"), py::arg("inputs_json"),
140
+ py::arg("reference_number_turns"), py::arg("weights_json") = json::object(),
141
+ py::arg("max_results") = 10);
142
+
143
+ m.def("calculate_cross_referenced_core_material", &calculate_cross_referenced_core_material,
144
+ R"pbdoc(
145
+ Rank core materials that could replace a reference material.
146
+
147
+ Args:
148
+ reference_core_material_json: the material being replaced.
149
+ temperature: operating temperature in Celsius (material properties are
150
+ strongly temperature dependent, so this is not optional).
151
+ weights_json: optional filter weights. Keys: "INITIAL_PERMEABILITY",
152
+ "REMANENCE", "COERCIVE_FORCE", "SATURATION",
153
+ "CURIE_TEMPERATURE", "VOLUMETRIC_LOSSES".
154
+ max_results: how many alternatives to return.
155
+
156
+ Returns:
157
+ {"data": [{"material", "scoring", "scoringPerFilter"}]} best first, or
158
+ {"data": "Exception: ..."} on failure.
159
+ )pbdoc",
160
+ py::arg("reference_core_material_json"), py::arg("temperature"),
161
+ py::arg("weights_json") = json::object(), py::arg("max_results") = 10);
162
+ }
163
+
164
+ } // namespace PyMKF
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+
3
+ #include "common.h"
4
+
5
+ namespace PyMKF {
6
+
7
+ // Core cross-referencer: given a reference core (shape + material + gapping) and
8
+ // the operating conditions, rank alternatives that could replace it.
9
+ json calculate_cross_referenced_core(json referenceCoreJson, json inputsJson,
10
+ int64_t referenceNumberTurns, json weightsJson,
11
+ int maximumNumberResults);
12
+
13
+ // Core-material cross-referencer: rank materials that could replace a reference
14
+ // material at a given temperature.
15
+ json calculate_cross_referenced_core_material(json referenceCoreMaterialJson, double temperature,
16
+ json weightsJson, int maximumNumberResults);
17
+
18
+ void register_crossref_bindings(py::module& m);
19
+
20
+ } // namespace PyMKF
@@ -309,13 +309,19 @@ json get_available_core_losses_methods(json magneticJson) {
309
309
  json calculate_filling_factor(json coilJson) {
310
310
  try {
311
311
  OpenMagnetics::Coil coil(coilJson, false);
312
- auto [areaFillingFactor, otherFactors] = coil.calculate_filling_factor();
313
- auto [overlappingFillingFactor, contiguousFillingFactor] = otherFactors;
312
+ // MKF main changed Coil::calculate_filling_factor() from
313
+ // std::pair<double, std::pair<double,double>> to a named
314
+ // FillingFactorsOutput struct (area / maxLayer / overlapping /
315
+ // contiguous / windingFits). Read the members directly; keep the
316
+ // original three keys and add the two new members.
317
+ auto fillingFactors = coil.calculate_filling_factor();
314
318
 
315
319
  json result;
316
- result["areaFillingFactor"] = areaFillingFactor;
317
- result["overlappingFillingFactor"] = overlappingFillingFactor;
318
- result["contiguousFillingFactor"] = contiguousFillingFactor;
320
+ result["areaFillingFactor"] = fillingFactors.areaFillingFactor;
321
+ result["overlappingFillingFactor"] = fillingFactors.overlappingFillingFactor;
322
+ result["contiguousFillingFactor"] = fillingFactors.contiguousFillingFactor;
323
+ result["maxLayerFillingFactor"] = fillingFactors.maxLayerFillingFactor;
324
+ result["windingFits"] = fillingFactors.windingFits;
319
325
  return result;
320
326
  }
321
327
  catch (const std::exception &exc) {
@@ -5,6 +5,7 @@
5
5
  #include "bobbin.h"
6
6
  #include "winding.h"
7
7
  #include "advisers.h"
8
+ #include "crossref.h"
8
9
  #include "converter.h" // converter surface re-pointed at Kirchhoff api (converter.cpp shims)
9
10
  #include "cmc.h" // CMC bindings re-pointed at Kirchhoff api::design_cmc (el-choker's path)
10
11
  #include "losses.h"
@@ -34,6 +35,7 @@ PYBIND11_MODULE(PyOpenMagnetics, m) {
34
35
  PyMKF::register_bobbin_bindings(m);
35
36
  PyMKF::register_winding_bindings(m);
36
37
  PyMKF::register_adviser_bindings(m);
38
+ PyMKF::register_crossref_bindings(m); // core / core-material cross-referencers
37
39
  PyMKF::register_converter_bindings(m); // converter surface via Kirchhoff
38
40
  PyMKF::register_cmc_bindings(m); // CMC via Kirchhoff (calculate_cmc_inputs + advanced)
39
41
  PyMKF::register_losses_bindings(m);
File without changes
File without changes