PyOpenMagnetics 1.1.3__tar.gz → 1.1.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.
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/PKG-INFO +7 -6
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/PyOpenMagnetics.pyi +35 -4
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/README.md +6 -5
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/examples/README.md +7 -6
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/examples/buck_inductor.py +9 -6
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/examples/flyback_design.py +22 -7
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/llms.txt +12 -7
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/02_buck_inductor.ipynb +25 -10
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/pyproject.toml +5 -3
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_magnetic_adviser.py +29 -15
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/.github/workflows/ci.yml +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/.github/workflows/publish.yml +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/.gitignore +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/CMakeLists.txt +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/LICENSE +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/api/MAS.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/api/mas_db_reader.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/api/validation.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/docs/compatibility.md +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/docs/errors.md +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/docs/performance.md +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/01_getting_started.ipynb +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/03_core_losses.ipynb +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/README.md +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/requirements.txt +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/advisers.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/advisers.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/bobbin.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/bobbin.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/common.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/core.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/core.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/database.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/database.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/logging.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/logging.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/losses.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/losses.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/module.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/plotting.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/plotting.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/settings.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/settings.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/simulation.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/simulation.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/utils.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/utils.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/winding.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/winding.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/wire.cpp +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/wire.h +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/test.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/__init__.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/conftest.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_core.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_core_adviser.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_examples_integration.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_inputs.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_logging.py +0 -0
- {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_winding.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: PyOpenMagnetics
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.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
|
|
@@ -121,12 +121,13 @@ processed_inputs = PyOpenMagnetics.process_inputs(inputs)
|
|
|
121
121
|
|
|
122
122
|
# Get magnetic recommendations
|
|
123
123
|
# core_mode: "available cores" (stock cores) or "standard cores" (all standard shapes)
|
|
124
|
-
|
|
124
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
# Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
|
|
127
|
+
for i, item in enumerate(result["data"]):
|
|
128
|
+
mag = item["mas"]["magnetic"]
|
|
129
|
+
core = mag["core"]["functionalDescription"]
|
|
130
|
+
print(f"{i+1}. {core['shape']['name']} - {core['material']['name']} (score: {item['scoring']:.3f})")
|
|
130
131
|
```
|
|
131
132
|
|
|
132
133
|
### Calculate Core Losses
|
|
@@ -505,6 +505,13 @@ def calculate_advised_cores(
|
|
|
505
505
|
weights: {"EFFICIENCY": 1.0, "DIMENSIONS": 0.5, "COST": 0.3}.
|
|
506
506
|
max_results: Maximum number of recommendations.
|
|
507
507
|
core_mode: "STANDARD_CORES" or "AVAILABLE_CORES" (stock only).
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
JSON object with "data" array containing ranked results.
|
|
511
|
+
Each result has:
|
|
512
|
+
- "mas": Mas object with magnetic, inputs, and optionally outputs
|
|
513
|
+
- "scoring": Overall float score
|
|
514
|
+
- "scoringPerFilter": Object with individual scores per filter
|
|
508
515
|
"""
|
|
509
516
|
...
|
|
510
517
|
|
|
@@ -512,11 +519,27 @@ def calculate_advised_magnetics(
|
|
|
512
519
|
inputs: Inputs,
|
|
513
520
|
max_results: int = 5,
|
|
514
521
|
core_mode: str = "STANDARD_CORES"
|
|
515
|
-
) ->
|
|
522
|
+
) -> JsonDict:
|
|
516
523
|
"""Get complete magnetic designs (core + winding).
|
|
517
524
|
|
|
525
|
+
Args:
|
|
526
|
+
inputs: Processed inputs (from process_inputs).
|
|
527
|
+
max_results: Maximum number of recommendations.
|
|
528
|
+
core_mode: "STANDARD_CORES" or "AVAILABLE_CORES" (stock only).
|
|
529
|
+
|
|
518
530
|
Returns:
|
|
519
|
-
|
|
531
|
+
JSON object with "data" array containing ranked results.
|
|
532
|
+
Each result has:
|
|
533
|
+
- "mas": Mas object with magnetic, inputs, and optionally outputs
|
|
534
|
+
- "scoring": Overall float score
|
|
535
|
+
- "scoringPerFilter": Object with individual scores per filter
|
|
536
|
+
(e.g., {"COST": 0.8, "LOSSES": 0.9, "DIMENSIONS": 0.7})
|
|
537
|
+
|
|
538
|
+
Example:
|
|
539
|
+
>>> result = PyOpenMagnetics.calculate_advised_magnetics(inputs, 5, "STANDARD_CORES")
|
|
540
|
+
>>> for item in result["data"]:
|
|
541
|
+
... mag = item["mas"]["magnetic"]
|
|
542
|
+
... print(f"Score: {item['scoring']}, Core: {mag['core']['functionalDescription']['shape']['name']}")
|
|
520
543
|
"""
|
|
521
544
|
...
|
|
522
545
|
|
|
@@ -524,8 +547,16 @@ def calculate_advised_magnetics_from_catalog(
|
|
|
524
547
|
inputs: Inputs,
|
|
525
548
|
catalog: List[Magnetic],
|
|
526
549
|
max_results: int = 5
|
|
527
|
-
) ->
|
|
528
|
-
"""Get designs from custom catalog of magnetics.
|
|
550
|
+
) -> JsonDict:
|
|
551
|
+
"""Get designs from custom catalog of magnetics.
|
|
552
|
+
|
|
553
|
+
Returns:
|
|
554
|
+
JSON object with "data" array containing ranked results.
|
|
555
|
+
Each result has:
|
|
556
|
+
- "mas": Mas object with magnetic data
|
|
557
|
+
- "scoring": Overall float score
|
|
558
|
+
- "scoringPerFilter": Object with individual scores per filter
|
|
559
|
+
"""
|
|
529
560
|
...
|
|
530
561
|
|
|
531
562
|
# =============================================================================
|
|
@@ -104,12 +104,13 @@ processed_inputs = PyOpenMagnetics.process_inputs(inputs)
|
|
|
104
104
|
|
|
105
105
|
# Get magnetic recommendations
|
|
106
106
|
# core_mode: "available cores" (stock cores) or "standard cores" (all standard shapes)
|
|
107
|
-
|
|
107
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
# Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
|
|
110
|
+
for i, item in enumerate(result["data"]):
|
|
111
|
+
mag = item["mas"]["magnetic"]
|
|
112
|
+
core = mag["core"]["functionalDescription"]
|
|
113
|
+
print(f"{i+1}. {core['shape']['name']} - {core['material']['name']} (score: {item['scoring']:.3f})")
|
|
113
114
|
```
|
|
114
115
|
|
|
115
116
|
### Calculate Core Losses
|
|
@@ -60,17 +60,18 @@ inputs = {
|
|
|
60
60
|
processed = PyOpenMagnetics.process_inputs(inputs)
|
|
61
61
|
|
|
62
62
|
# 3. Get recommendations
|
|
63
|
-
|
|
63
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(processed, 5, "STANDARD_CORES")
|
|
64
64
|
|
|
65
|
-
# 4. Analyze results
|
|
66
|
-
for
|
|
65
|
+
# 4. Analyze results - result["data"] contains list of {mas, scoring, scoringPerFilter}
|
|
66
|
+
for item in result["data"]:
|
|
67
|
+
mag = item["mas"]["magnetic"]
|
|
67
68
|
losses = PyOpenMagnetics.calculate_core_losses(
|
|
68
|
-
mag["
|
|
69
|
-
mag["
|
|
69
|
+
mag["core"],
|
|
70
|
+
mag["coil"],
|
|
70
71
|
processed,
|
|
71
72
|
{"coreLosses": "IGSE", "reluctance": "ZHANG"}
|
|
72
73
|
)
|
|
73
|
-
print(f"Core losses: {losses['coreLosses']:.3f} W")
|
|
74
|
+
print(f"Core losses: {losses['coreLosses']:.3f} W, Score: {item['scoring']:.3f}")
|
|
74
75
|
```
|
|
75
76
|
|
|
76
77
|
## Additional Resources
|
|
@@ -104,12 +104,13 @@ def design_buck_inductor():
|
|
|
104
104
|
"COST": 0.3
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
processed,
|
|
109
|
-
max_results=5,
|
|
110
|
-
core_mode="STANDARD_CORES"
|
|
107
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(
|
|
108
|
+
processed, 5, "STANDARD_CORES"
|
|
111
109
|
)
|
|
112
110
|
|
|
111
|
+
# Extract magnetics list from result (v1.1.2+ format: {"data": [...]})
|
|
112
|
+
magnetics = result["data"] if isinstance(result, dict) and "data" in result else result
|
|
113
|
+
|
|
113
114
|
print(f" Found {len(magnetics)} suitable designs")
|
|
114
115
|
|
|
115
116
|
# Analyze designs
|
|
@@ -121,8 +122,10 @@ def design_buck_inductor():
|
|
|
121
122
|
"reluctance": "ZHANG"
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
for i,
|
|
125
|
-
|
|
125
|
+
for i, item in enumerate(magnetics[:3]):
|
|
126
|
+
# In v1.1.2+, each item has "mas" containing the magnetic data
|
|
127
|
+
mas = item.get("mas", item) if isinstance(item, dict) else item
|
|
128
|
+
if not isinstance(mas, dict) or "magnetic" not in mas:
|
|
126
129
|
continue
|
|
127
130
|
|
|
128
131
|
magnetic = mas["magnetic"]
|
|
@@ -107,12 +107,18 @@ def design_flyback_transformer():
|
|
|
107
107
|
"COST": 0.3 # Tertiary: low cost
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
processed_inputs,
|
|
112
|
-
max_results=3,
|
|
113
|
-
core_mode="STANDARD_CORES"
|
|
110
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(
|
|
111
|
+
processed_inputs, 3, "STANDARD_CORES"
|
|
114
112
|
)
|
|
115
113
|
|
|
114
|
+
# Extract magnetics list from result (v1.1.2+ format: {"data": [...]})
|
|
115
|
+
# Note: If there's an error, data will be a string containing the exception message
|
|
116
|
+
data = result.get("data", result) if isinstance(result, dict) else result
|
|
117
|
+
if isinstance(data, str):
|
|
118
|
+
print(f" ✗ Error: {data}")
|
|
119
|
+
return None
|
|
120
|
+
magnetics = data
|
|
121
|
+
|
|
116
122
|
print(f" ✓ Found {len(magnetics)} suitable designs")
|
|
117
123
|
|
|
118
124
|
# Step 4: Analyze top recommendations
|
|
@@ -125,8 +131,10 @@ def design_flyback_transformer():
|
|
|
125
131
|
"coreTemperature": "MANIKTALA"
|
|
126
132
|
}
|
|
127
133
|
|
|
128
|
-
for i,
|
|
129
|
-
|
|
134
|
+
for i, item in enumerate(magnetics):
|
|
135
|
+
# In v1.1.2+, each item has "mas" containing the magnetic data
|
|
136
|
+
mas = item.get("mas", item) if isinstance(item, dict) else item
|
|
137
|
+
if not isinstance(mas, dict) or "magnetic" not in mas:
|
|
130
138
|
continue
|
|
131
139
|
|
|
132
140
|
magnetic = mas["magnetic"]
|
|
@@ -154,6 +162,9 @@ def design_flyback_transformer():
|
|
|
154
162
|
total_loss = core_loss + winding_loss
|
|
155
163
|
|
|
156
164
|
print(f"\nDesign #{i+1}: {shape_name} / {material_name}")
|
|
165
|
+
# Show scoring if available (v1.1.2+)
|
|
166
|
+
if 'scoring' in item:
|
|
167
|
+
print(f" Score: {item['scoring']:.3f}")
|
|
157
168
|
print(f" Core losses: {core_loss:.3f} W")
|
|
158
169
|
print(f" Winding losses: {winding_loss:.3f} W")
|
|
159
170
|
print(f" Total losses: {total_loss:.3f} W")
|
|
@@ -167,7 +178,11 @@ def design_flyback_transformer():
|
|
|
167
178
|
print("\n" + "=" * 60)
|
|
168
179
|
print("Design complete! Best design is #1")
|
|
169
180
|
|
|
170
|
-
|
|
181
|
+
# Return the first item's mas for backward compatibility
|
|
182
|
+
if magnetics:
|
|
183
|
+
first_item = magnetics[0]
|
|
184
|
+
return first_item.get("mas", first_item) if isinstance(first_item, dict) else first_item
|
|
185
|
+
return None
|
|
171
186
|
|
|
172
187
|
|
|
173
188
|
def explore_core_database():
|
|
@@ -368,21 +368,25 @@ cores = PyOpenMagnetics.calculate_advised_cores(
|
|
|
368
368
|
)
|
|
369
369
|
|
|
370
370
|
# Get complete magnetic designs
|
|
371
|
-
|
|
371
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(
|
|
372
372
|
processed,
|
|
373
373
|
max_results=5,
|
|
374
374
|
core_mode="STANDARD_CORES"
|
|
375
375
|
)
|
|
376
376
|
|
|
377
|
-
#
|
|
378
|
-
for
|
|
379
|
-
|
|
380
|
-
|
|
377
|
+
# Result structure: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
|
|
378
|
+
for item in result["data"]:
|
|
379
|
+
mag = item["mas"]["magnetic"]
|
|
380
|
+
core_name = mag["core"]["functionalDescription"]["shape"]["name"]
|
|
381
|
+
material = mag["core"]["functionalDescription"]["material"]["name"]
|
|
382
|
+
score = item["scoring"]
|
|
383
|
+
print(f"{core_name} - {material} (score: {score:.3f})")
|
|
381
384
|
|
|
382
385
|
# From custom catalog
|
|
383
|
-
|
|
386
|
+
catalog_result = PyOpenMagnetics.calculate_advised_magnetics_from_catalog(
|
|
384
387
|
processed, catalog_magnetics, max_results=5
|
|
385
388
|
)
|
|
389
|
+
# Same result structure as calculate_advised_magnetics
|
|
386
390
|
```
|
|
387
391
|
|
|
388
392
|
### Simulation
|
|
@@ -538,7 +542,8 @@ flyback = {
|
|
|
538
542
|
"desiredTurnsRatios": [8.0, 19.2] # N_pri/N_sec for each output
|
|
539
543
|
}
|
|
540
544
|
inputs = PyOpenMagnetics.process_flyback(flyback)
|
|
541
|
-
|
|
545
|
+
result = PyOpenMagnetics.calculate_advised_magnetics(inputs, 5, "STANDARD_CORES")
|
|
546
|
+
# Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
|
|
542
547
|
```
|
|
543
548
|
|
|
544
549
|
### Buck Converter (Non-Isolated Step-Down)
|
|
@@ -153,20 +153,26 @@
|
|
|
153
153
|
"# Get magnetic design recommendations\n",
|
|
154
154
|
"print(\"\\nSearching for optimal designs...\")\n",
|
|
155
155
|
"try:\n",
|
|
156
|
-
"
|
|
156
|
+
" result = PyOpenMagnetics.calculate_advised_magnetics(\n",
|
|
157
157
|
" processed,\n",
|
|
158
158
|
" max_results=5,\n",
|
|
159
159
|
" core_mode=\"STANDARD_CORES\"\n",
|
|
160
160
|
" )\n",
|
|
161
161
|
" \n",
|
|
162
|
+
" # Extract magnetics list from result (v1.1.2+ format: {\"data\": [...]})\n",
|
|
163
|
+
" magnetics = result[\"data\"] if isinstance(result, dict) and \"data\" in result else result\n",
|
|
164
|
+
" \n",
|
|
162
165
|
" print(f\"\\nFound {len(magnetics)} suitable designs:\")\n",
|
|
163
|
-
" for i,
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
+
" for i, item in enumerate(magnetics[:5]):\n",
|
|
167
|
+
" # In v1.1.2+, each item has \"mas\" containing the magnetic data\n",
|
|
168
|
+
" mas = item.get(\"mas\", item) if isinstance(item, dict) else item\n",
|
|
169
|
+
" if isinstance(mas, dict) and 'magnetic' in mas:\n",
|
|
170
|
+
" magnetic = mas['magnetic']\n",
|
|
166
171
|
" core = magnetic['core']['functionalDescription']\n",
|
|
167
172
|
" shape_name = core['shape']['name'] if isinstance(core['shape'], dict) else core['shape']\n",
|
|
168
173
|
" mat_name = core['material']['name'] if isinstance(core['material'], dict) else core['material']\n",
|
|
169
|
-
"
|
|
174
|
+
" score = item.get('scoring', 'N/A')\n",
|
|
175
|
+
" print(f\" {i+1}. {shape_name} / {mat_name} (score: {score})\")\n",
|
|
170
176
|
"except Exception as e:\n",
|
|
171
177
|
" print(f\"Adviser error (may need more compute time): {e}\")"
|
|
172
178
|
]
|
|
@@ -236,9 +242,14 @@
|
|
|
236
242
|
" if 'magnetics' in dir() and len(magnetics) > 0:\n",
|
|
237
243
|
" print(\"=== Best Design Analysis ===\\n\")\n",
|
|
238
244
|
" \n",
|
|
239
|
-
" best
|
|
240
|
-
"
|
|
241
|
-
"
|
|
245
|
+
" # Get best result (first in the list)\n",
|
|
246
|
+
" best_item = magnetics[0]\n",
|
|
247
|
+
" \n",
|
|
248
|
+
" # In v1.1.2+, each item has \"mas\" containing the magnetic data\n",
|
|
249
|
+
" best_mas = best_item.get(\"mas\", best_item) if isinstance(best_item, dict) else best_item\n",
|
|
250
|
+
" \n",
|
|
251
|
+
" if isinstance(best_mas, dict) and 'magnetic' in best_mas:\n",
|
|
252
|
+
" magnetic = best_mas['magnetic']\n",
|
|
242
253
|
" core_fd = magnetic['core']['functionalDescription']\n",
|
|
243
254
|
" \n",
|
|
244
255
|
" # Extract shape and material names\n",
|
|
@@ -248,6 +259,10 @@
|
|
|
248
259
|
" print(f\"Shape: {shape}\")\n",
|
|
249
260
|
" print(f\"Material: {material}\")\n",
|
|
250
261
|
" \n",
|
|
262
|
+
" # Show scoring if available (v1.1.2+)\n",
|
|
263
|
+
" if 'scoring' in best_item:\n",
|
|
264
|
+
" print(f\"Score: {best_item['scoring']:.3f}\")\n",
|
|
265
|
+
" \n",
|
|
251
266
|
" # Check gapping\n",
|
|
252
267
|
" gapping = core_fd.get('gapping', [])\n",
|
|
253
268
|
" total_gap = sum(g.get('length', 0) for g in gapping) * 1000\n",
|
|
@@ -263,8 +278,8 @@
|
|
|
263
278
|
" print(f\" Parallels: {winding.get('numberParallels', 1)}\")\n",
|
|
264
279
|
" \n",
|
|
265
280
|
" # Show outputs if available\n",
|
|
266
|
-
" if 'outputs' in
|
|
267
|
-
" outputs =
|
|
281
|
+
" if 'outputs' in best_mas:\n",
|
|
282
|
+
" outputs = best_mas['outputs']\n",
|
|
268
283
|
" print(f\"\\nSimulation Results:\")\n",
|
|
269
284
|
" if 'coreLosses' in outputs:\n",
|
|
270
285
|
" print(f\" Core losses: {outputs['coreLosses']:.3f} W\")\n",
|
|
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "PyOpenMagnetics"
|
|
7
|
-
version = "1.1.
|
|
7
|
+
version = "1.1.4"
|
|
8
8
|
requires-python = ">=3.8"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Alfonso Martinez", email="Alfonso_VII@hotmail.com" },
|
|
@@ -56,11 +56,13 @@ before-all = [
|
|
|
56
56
|
"npm --version",
|
|
57
57
|
"npm install -g quicktype@23.0.170"
|
|
58
58
|
]
|
|
59
|
+
environment = { GIT_LFS_SKIP_SMUDGE=1, CMAKE_BUILD_PARALLEL_LEVEL="4" }
|
|
59
60
|
|
|
60
61
|
[tool.cibuildwheel.macos]
|
|
61
62
|
before-all = "npm --version && npm install -g quicktype@23.0.170"
|
|
62
|
-
environment = { MACOSX_DEPLOYMENT_TARGET="14.0", GIT_LFS_SKIP_SMUDGE=1 }
|
|
63
|
+
environment = { MACOSX_DEPLOYMENT_TARGET="14.0", GIT_LFS_SKIP_SMUDGE=1, CMAKE_BUILD_PARALLEL_LEVEL="3" }
|
|
63
64
|
|
|
64
65
|
[tool.cibuildwheel.windows]
|
|
65
66
|
before-all = "rmdir /S /Q build && npm --version && npm install -g quicktype@23.0.170"
|
|
66
|
-
archs = ["AMD64"]
|
|
67
|
+
archs = ["AMD64"]
|
|
68
|
+
environment = { GIT_LFS_SKIP_SMUDGE=1, CMAKE_BUILD_PARALLEL_LEVEL="2" }
|
|
@@ -17,6 +17,19 @@ def parse_json_result(result):
|
|
|
17
17
|
return result
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def extract_magnetics_list(result):
|
|
21
|
+
"""
|
|
22
|
+
Extract list of magnetics from result.
|
|
23
|
+
|
|
24
|
+
In version 1.1.2+, the function returns {"data": [{"mas": {...}, "scoring": ..., ...}, ...]}
|
|
25
|
+
In version 1.1.0, it returned a list directly.
|
|
26
|
+
"""
|
|
27
|
+
parsed = parse_json_result(result)
|
|
28
|
+
if isinstance(parsed, dict) and "data" in parsed:
|
|
29
|
+
return parsed["data"]
|
|
30
|
+
return parsed
|
|
31
|
+
|
|
32
|
+
|
|
20
33
|
class TestMagneticAdviserBasic:
|
|
21
34
|
"""
|
|
22
35
|
Basic magnetic adviser tests.
|
|
@@ -32,7 +45,7 @@ class TestMagneticAdviserBasic:
|
|
|
32
45
|
|
|
33
46
|
# API: calculate_advised_magnetics(inputs, max_results, core_mode)
|
|
34
47
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
35
|
-
results =
|
|
48
|
+
results = extract_magnetics_list(result_json)
|
|
36
49
|
|
|
37
50
|
assert isinstance(results, list)
|
|
38
51
|
# Should return some results
|
|
@@ -45,15 +58,16 @@ class TestMagneticAdviserBasic:
|
|
|
45
58
|
processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
|
|
46
59
|
|
|
47
60
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 3, "available cores")
|
|
48
|
-
results =
|
|
61
|
+
results = extract_magnetics_list(result_json)
|
|
49
62
|
|
|
50
63
|
if len(results) > 0:
|
|
51
64
|
for result in results:
|
|
52
65
|
assert isinstance(result, dict)
|
|
53
|
-
# Each result should
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
# Each result should have "mas" containing the magnetic data (v1.1.2+ format)
|
|
67
|
+
# or "magnetic" directly (v1.1.0 format)
|
|
68
|
+
mas = result.get("mas", result)
|
|
69
|
+
if isinstance(mas, dict) and "magnetic" in mas:
|
|
70
|
+
assert "core" in mas["magnetic"] or "coil" in mas["magnetic"]
|
|
57
71
|
|
|
58
72
|
|
|
59
73
|
class TestMagneticAdviserCoreModes:
|
|
@@ -70,7 +84,7 @@ class TestMagneticAdviserCoreModes:
|
|
|
70
84
|
processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
|
|
71
85
|
|
|
72
86
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
73
|
-
results =
|
|
87
|
+
results = extract_magnetics_list(result_json)
|
|
74
88
|
|
|
75
89
|
assert isinstance(results, list)
|
|
76
90
|
|
|
@@ -82,7 +96,7 @@ class TestMagneticAdviserCoreModes:
|
|
|
82
96
|
processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
|
|
83
97
|
|
|
84
98
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
|
|
85
|
-
results =
|
|
99
|
+
results = extract_magnetics_list(result_json)
|
|
86
100
|
|
|
87
101
|
assert isinstance(results, list)
|
|
88
102
|
|
|
@@ -95,7 +109,7 @@ class TestMagneticAdviserInputTypes:
|
|
|
95
109
|
processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
|
|
96
110
|
|
|
97
111
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
98
|
-
results =
|
|
112
|
+
results = extract_magnetics_list(result_json)
|
|
99
113
|
|
|
100
114
|
assert isinstance(results, list)
|
|
101
115
|
|
|
@@ -108,7 +122,7 @@ class TestMagneticAdviserInputTypes:
|
|
|
108
122
|
processed_inputs = PyOpenMagnetics.process_inputs(transformer_inputs)
|
|
109
123
|
|
|
110
124
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
111
|
-
results =
|
|
125
|
+
results = extract_magnetics_list(result_json)
|
|
112
126
|
|
|
113
127
|
assert isinstance(results, list)
|
|
114
128
|
|
|
@@ -121,7 +135,7 @@ class TestMagneticAdviserInputTypes:
|
|
|
121
135
|
processed_inputs = PyOpenMagnetics.process_inputs(high_frequency_inputs)
|
|
122
136
|
|
|
123
137
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
124
|
-
results =
|
|
138
|
+
results = extract_magnetics_list(result_json)
|
|
125
139
|
|
|
126
140
|
assert isinstance(results, list)
|
|
127
141
|
|
|
@@ -134,7 +148,7 @@ class TestMagneticAdviserInputTypes:
|
|
|
134
148
|
processed_inputs = PyOpenMagnetics.process_inputs(flyback_inputs)
|
|
135
149
|
|
|
136
150
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
137
|
-
results =
|
|
151
|
+
results = extract_magnetics_list(result_json)
|
|
138
152
|
|
|
139
153
|
assert isinstance(results, list)
|
|
140
154
|
|
|
@@ -149,10 +163,10 @@ class TestMagneticAdviserFiltering:
|
|
|
149
163
|
"""
|
|
150
164
|
processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
|
|
151
165
|
|
|
152
|
-
results_5 =
|
|
166
|
+
results_5 = extract_magnetics_list(
|
|
153
167
|
PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
|
|
154
168
|
)
|
|
155
|
-
results_2 =
|
|
169
|
+
results_2 = extract_magnetics_list(
|
|
156
170
|
PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 2, "available cores")
|
|
157
171
|
)
|
|
158
172
|
|
|
@@ -167,7 +181,7 @@ class TestMagneticAdviserFiltering:
|
|
|
167
181
|
processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
|
|
168
182
|
|
|
169
183
|
result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 1, "available cores")
|
|
170
|
-
results =
|
|
184
|
+
results = extract_magnetics_list(result_json)
|
|
171
185
|
|
|
172
186
|
assert len(results) <= 1
|
|
173
187
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|