PyOpenMagnetics 1.3.10__tar.gz → 1.3.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/CMakeLists.txt +14 -2
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/PKG-INFO +1 -1
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/PyOpenMagnetics.pyi +36 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/pyproject.toml +1 -1
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/converter.cpp +495 -3
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/converter.h +11 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/.github/workflows/ci.yml +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/.github/workflows/publish.yml +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/.gitignore +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/AGENTS.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/LICENSE +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/README.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/api/MAS.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/api/mas_db_reader.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/api/validation.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/clear_cibuildwheel_cache.sh +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/docs/compatibility.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/docs/errors.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/docs/performance.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/README.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/buck_inductor.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/complete_simulation_example.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/converter_design_example.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/debug_bobbin.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/debug_coil.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/debug_core.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/debug_plotting.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_220v_12v_1a.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_220v_12v_2a_complete.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_bh_curve.png +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_core.png +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_design.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_summary.png +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/flyback_waveforms.png +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/list_plot_funcs.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/plot_flyback_design.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/plot_flyback_pyom.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/test_field_calc.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/examples/test_field_plot.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/force_fresh_build.sh +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/llms.txt +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/notebooks/01_getting_started.ipynb +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/notebooks/02_buck_inductor.ipynb +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/notebooks/03_core_losses.ipynb +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/notebooks/README.md +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/requirements.txt +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/advisers.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/advisers.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/bobbin.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/bobbin.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/common.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/core.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/core.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/database.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/database.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/logging.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/logging.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/losses.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/losses.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/module.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/plotting.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/plotting.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/settings.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/settings.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/simulation.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/simulation.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/utils.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/utils.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/winding.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/winding.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/wire.cpp +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/src/wire.h +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/test.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/__init__.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/conftest.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_converter_endpoints.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_core.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_core_adviser.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_examples_integration.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_inputs.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_logging.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_magnetic_adviser.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_plotting.py +0 -0
- {pyopenmagnetics-1.3.10 → pyopenmagnetics-1.3.12}/tests/test_winding.py +0 -0
|
@@ -232,7 +232,6 @@ add_custom_command(
|
|
|
232
232
|
-S ${MAS_DIR}/schemas/inputs/topologies/currentTransformer.json
|
|
233
233
|
-S ${MAS_DIR}/schemas/inputs/topologies/boost.json
|
|
234
234
|
-S ${MAS_DIR}/schemas/inputs/topologies/buck.json
|
|
235
|
-
-S ${MAS_DIR}/schemas/inputs/topologies/flybuck.json
|
|
236
235
|
-S ${MAS_DIR}/schemas/inputs/topologies/forward.json
|
|
237
236
|
-S ${MAS_DIR}/schemas/inputs/topologies/isolatedBuck.json
|
|
238
237
|
-S ${MAS_DIR}/schemas/inputs/topologies/isolatedBuckBoost.json
|
|
@@ -240,7 +239,20 @@ add_custom_command(
|
|
|
240
239
|
-S ${MAS_DIR}/schemas/inputs/topologies/dualActiveBridge.json
|
|
241
240
|
-S ${MAS_DIR}/schemas/inputs/topologies/llcResonant.json
|
|
242
241
|
-S ${MAS_DIR}/schemas/inputs/topologies/cllcResonant.json
|
|
243
|
-
-S ${MAS_DIR}/schemas/inputs/topologies/
|
|
242
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/clllcResonant.json
|
|
243
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/phaseShiftedFullBridge.json
|
|
244
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/phaseShiftedHalfBridge.json
|
|
245
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/powerFactorCorrection.json
|
|
246
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/commonModeChoke.json
|
|
247
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/differentialModeChoke.json
|
|
248
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/asymmetricHalfBridge.json
|
|
249
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/cuk.json
|
|
250
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/sepic.json
|
|
251
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/zeta.json
|
|
252
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/weinberg.json
|
|
253
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/fourSwitchBuckBoost.json
|
|
254
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/seriesResonant.json
|
|
255
|
+
-S ${MAS_DIR}/schemas/inputs/topologies/vienna.json
|
|
244
256
|
-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
|
|
245
257
|
USES_TERMINAL)
|
|
246
258
|
|
|
@@ -960,3 +960,39 @@ def process_isolated_buck_boost(isolated_buck_boost: JsonDict) -> Inputs:
|
|
|
960
960
|
def process_current_transformer(ct: JsonDict, turns_ratio: float, secondary_resistance: float = 0.0) -> Inputs:
|
|
961
961
|
"""Process Current Transformer specification to Inputs."""
|
|
962
962
|
...
|
|
963
|
+
|
|
964
|
+
def process_cuk(cuk: JsonDict) -> Inputs:
|
|
965
|
+
"""Process Cuk converter specification to Inputs."""
|
|
966
|
+
...
|
|
967
|
+
|
|
968
|
+
def process_sepic(sepic: JsonDict) -> Inputs:
|
|
969
|
+
"""Process SEPIC converter specification to Inputs."""
|
|
970
|
+
...
|
|
971
|
+
|
|
972
|
+
def process_zeta(zeta: JsonDict) -> Inputs:
|
|
973
|
+
"""Process Zeta converter specification to Inputs."""
|
|
974
|
+
...
|
|
975
|
+
|
|
976
|
+
def process_four_switch_buck_boost(converter: JsonDict) -> Inputs:
|
|
977
|
+
"""Process Four-Switch Buck-Boost converter specification to Inputs."""
|
|
978
|
+
...
|
|
979
|
+
|
|
980
|
+
def process_asymmetric_half_bridge(converter: JsonDict) -> Inputs:
|
|
981
|
+
"""Process Asymmetric Half-Bridge converter specification to Inputs."""
|
|
982
|
+
...
|
|
983
|
+
|
|
984
|
+
def process_weinberg(converter: JsonDict) -> Inputs:
|
|
985
|
+
"""Process Weinberg converter specification to Inputs."""
|
|
986
|
+
...
|
|
987
|
+
|
|
988
|
+
def process_vienna(converter: JsonDict) -> Inputs:
|
|
989
|
+
"""Process Vienna Rectifier converter specification to Inputs."""
|
|
990
|
+
...
|
|
991
|
+
|
|
992
|
+
def process_clllc(converter: JsonDict) -> Inputs:
|
|
993
|
+
"""Process CLLLC Resonant converter specification to Inputs."""
|
|
994
|
+
...
|
|
995
|
+
|
|
996
|
+
def process_src(converter: JsonDict) -> Inputs:
|
|
997
|
+
"""Process Series Resonant Converter (SRC) specification to Inputs."""
|
|
998
|
+
...
|
|
@@ -17,9 +17,134 @@
|
|
|
17
17
|
#include "converter_models/IsolatedBuckBoost.h"
|
|
18
18
|
#include "converter_models/CurrentTransformer.h"
|
|
19
19
|
#include "converter_models/PowerFactorCorrection.h"
|
|
20
|
+
#include "converter_models/Cuk.h"
|
|
21
|
+
#include "converter_models/Sepic.h"
|
|
22
|
+
#include "converter_models/Zeta.h"
|
|
23
|
+
#include "converter_models/FourSwitchBuckBoost.h"
|
|
24
|
+
#include "converter_models/AsymmetricHalfBridge.h"
|
|
25
|
+
#include "converter_models/Weinberg.h"
|
|
26
|
+
#include "converter_models/Vienna.h"
|
|
27
|
+
#include "converter_models/Clllc.h"
|
|
28
|
+
#include "converter_models/Src.h"
|
|
29
|
+
#include "constructive_models/MasMigration.h"
|
|
30
|
+
|
|
31
|
+
#include <set>
|
|
32
|
+
#include <unordered_map>
|
|
20
33
|
|
|
21
34
|
namespace PyMKF {
|
|
22
35
|
|
|
36
|
+
// ------------------------------------------------------------------
|
|
37
|
+
// Topology name normalization.
|
|
38
|
+
//
|
|
39
|
+
// dispatch_converter() below uses legacy short forms ("flyback", "buck",
|
|
40
|
+
// ...). External callers may pass:
|
|
41
|
+
// * the same short form (canonical internal),
|
|
42
|
+
// * the MAS 1.0 camelCase enum value ("flybackConverter", ...),
|
|
43
|
+
// * or the pre-1.0 Title Case label ("Flyback Converter", ...).
|
|
44
|
+
//
|
|
45
|
+
// Normalize all three to the internal short form so process_converter()
|
|
46
|
+
// and design_magnetics_from_converter() transparently accept any of them.
|
|
47
|
+
// ------------------------------------------------------------------
|
|
48
|
+
static std::string normalize_topology_name(const std::string& s) {
|
|
49
|
+
static const std::set<std::string> short_forms = {
|
|
50
|
+
"flyback", "advanced_flyback",
|
|
51
|
+
"buck", "advanced_buck",
|
|
52
|
+
"boost", "advanced_boost",
|
|
53
|
+
"single_switch_forward",
|
|
54
|
+
"two_switch_forward",
|
|
55
|
+
"active_clamp_forward",
|
|
56
|
+
"push_pull",
|
|
57
|
+
"llc", "advanced_llc",
|
|
58
|
+
"cllc", "advanced_cllc",
|
|
59
|
+
"dab", "advanced_dab",
|
|
60
|
+
"phase_shifted_full_bridge", "psfb",
|
|
61
|
+
"phase_shifted_half_bridge", "pshb",
|
|
62
|
+
"isolated_buck",
|
|
63
|
+
"isolated_buck_boost",
|
|
64
|
+
"current_transformer",
|
|
65
|
+
"power_factor_correction", "pfc",
|
|
66
|
+
"cuk", "advanced_cuk",
|
|
67
|
+
"sepic", "advanced_sepic",
|
|
68
|
+
"zeta", "advanced_zeta",
|
|
69
|
+
"four_switch_buck_boost", "advanced_four_switch_buck_boost",
|
|
70
|
+
"asymmetric_half_bridge", "advanced_asymmetric_half_bridge",
|
|
71
|
+
"weinberg", "advanced_weinberg",
|
|
72
|
+
"vienna", "advanced_vienna",
|
|
73
|
+
"clllc", "advanced_clllc",
|
|
74
|
+
"src", "advanced_src"
|
|
75
|
+
};
|
|
76
|
+
if (short_forms.count(s)) return s;
|
|
77
|
+
|
|
78
|
+
static const std::unordered_map<std::string, std::string> aliases = {
|
|
79
|
+
// MAS 1.0 camelCase (canonical for designRequirements.topology)
|
|
80
|
+
{"flybackConverter", "flyback"},
|
|
81
|
+
{"buckConverter", "buck"},
|
|
82
|
+
{"boostConverter", "boost"},
|
|
83
|
+
{"singleSwitchForwardConverter", "single_switch_forward"},
|
|
84
|
+
{"twoSwitchForwardConverter", "two_switch_forward"},
|
|
85
|
+
{"activeClampForwardConverter", "active_clamp_forward"},
|
|
86
|
+
{"pushPullConverter", "push_pull"},
|
|
87
|
+
{"llcResonantConverter", "llc"},
|
|
88
|
+
{"llcConverter", "llc"},
|
|
89
|
+
{"cllcResonantConverter", "cllc"},
|
|
90
|
+
{"cllcConverter", "cllc"},
|
|
91
|
+
{"dualActiveBridgeConverter", "dab"},
|
|
92
|
+
{"phaseShiftedFullBridgeConverter", "phase_shifted_full_bridge"},
|
|
93
|
+
{"phaseShiftedHalfBridgeConverter", "phase_shifted_half_bridge"},
|
|
94
|
+
{"isolatedBuckConverter", "isolated_buck"},
|
|
95
|
+
{"isolatedBuckBoostConverter", "isolated_buck_boost"},
|
|
96
|
+
{"currentTransformer", "current_transformer"},
|
|
97
|
+
{"powerFactorCorrection", "power_factor_correction"},
|
|
98
|
+
{"cukConverter", "cuk"},
|
|
99
|
+
{"sepicConverter", "sepic"},
|
|
100
|
+
{"zetaConverter", "zeta"},
|
|
101
|
+
{"fourSwitchBuckBoostConverter", "four_switch_buck_boost"},
|
|
102
|
+
{"asymmetricHalfBridgeConverter", "asymmetric_half_bridge"},
|
|
103
|
+
{"weinbergConverter", "weinberg"},
|
|
104
|
+
{"viennaRectifierConverter", "vienna"},
|
|
105
|
+
{"clllcResonantConverter", "clllc"},
|
|
106
|
+
{"seriesResonantConverter", "src"},
|
|
107
|
+
|
|
108
|
+
// Pre-1.0 Title Case labels
|
|
109
|
+
{"Flyback Converter", "flyback"},
|
|
110
|
+
{"Buck Converter", "buck"},
|
|
111
|
+
{"Boost Converter", "boost"},
|
|
112
|
+
{"Single-Switch Forward Converter", "single_switch_forward"},
|
|
113
|
+
{"Two-Switch Forward Converter", "two_switch_forward"},
|
|
114
|
+
{"Active-Clamp Forward Converter", "active_clamp_forward"},
|
|
115
|
+
{"Push-Pull Converter", "push_pull"},
|
|
116
|
+
{"LLC Resonant Converter", "llc"},
|
|
117
|
+
{"LLC Converter", "llc"},
|
|
118
|
+
{"CLLC Resonant Converter", "cllc"},
|
|
119
|
+
{"Dual Active Bridge Converter", "dab"},
|
|
120
|
+
{"Phase-Shifted Full Bridge Converter", "phase_shifted_full_bridge"},
|
|
121
|
+
{"Phase-Shifted Half Bridge Converter", "phase_shifted_half_bridge"},
|
|
122
|
+
{"Isolated Buck Converter", "isolated_buck"},
|
|
123
|
+
{"Isolated Buck-Boost Converter", "isolated_buck_boost"},
|
|
124
|
+
{"Current Transformer", "current_transformer"},
|
|
125
|
+
{"Power Factor Correction", "power_factor_correction"},
|
|
126
|
+
{"Cuk Converter", "cuk"},
|
|
127
|
+
{"SEPIC Converter", "sepic"},
|
|
128
|
+
{"Sepic Converter", "sepic"},
|
|
129
|
+
{"Zeta Converter", "zeta"},
|
|
130
|
+
{"Four-Switch Buck-Boost Converter", "four_switch_buck_boost"},
|
|
131
|
+
{"Asymmetric Half-Bridge Converter", "asymmetric_half_bridge"},
|
|
132
|
+
{"Weinberg Converter", "weinberg"},
|
|
133
|
+
{"Vienna Rectifier Converter", "vienna"},
|
|
134
|
+
{"Vienna Rectifier", "vienna"},
|
|
135
|
+
{"CLLLC Resonant Converter", "clllc"},
|
|
136
|
+
{"Series Resonant Converter", "src"},
|
|
137
|
+
{"SRC", "src"}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
auto it = aliases.find(s);
|
|
141
|
+
if (it != aliases.end()) return it->second;
|
|
142
|
+
|
|
143
|
+
// Pass through unchanged; dispatch_converter() will throw if it is
|
|
144
|
+
// truly unknown. We never silently substitute an unrelated topology.
|
|
145
|
+
return s;
|
|
146
|
+
}
|
|
147
|
+
|
|
23
148
|
OpenMagnetics::Inputs process_flyback_internal(const json& converterJson, bool useNgspice) {
|
|
24
149
|
OpenMagnetics::AdvancedFlyback converter(converterJson);
|
|
25
150
|
converter._assertErrors = true;
|
|
@@ -363,6 +488,195 @@ OpenMagnetics::Inputs process_pfc_internal(const json& converterJson) {
|
|
|
363
488
|
return converter.process();
|
|
364
489
|
}
|
|
365
490
|
|
|
491
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
492
|
+
// 9 new topology bindings (2026-05): Cuk, Sepic, Zeta,
|
|
493
|
+
// FourSwitchBuckBoost, AsymmetricHalfBridge, Weinberg, Vienna, Clllc,
|
|
494
|
+
// Src. All have first-class implementations in MKF's converter_models/
|
|
495
|
+
// — they were just not wired through PyMKF until now.
|
|
496
|
+
//
|
|
497
|
+
// Pattern groups:
|
|
498
|
+
// * Single-inductor non-isolated (Cuk, Sepic, Zeta, FSBB) follow the
|
|
499
|
+
// Buck/Boost pattern: AdvancedXxx::process() + simulate via inductance.
|
|
500
|
+
// * Isolated with vector turns ratios (AsymHB, Clllc) follow the LLC
|
|
501
|
+
// pattern.
|
|
502
|
+
// * Weinberg has scalar turns ratio (single-secondary topology) — its
|
|
503
|
+
// ngspice dispatch lives separately below.
|
|
504
|
+
// * Vienna and Src have AdvancedXxx classes that only override
|
|
505
|
+
// process_design_requirements(); the inherited Topology::process()
|
|
506
|
+
// handles them. They follow the PFC pattern (no useNgspice branch).
|
|
507
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
508
|
+
|
|
509
|
+
OpenMagnetics::Inputs process_cuk_internal(const json& converterJson, bool useNgspice) {
|
|
510
|
+
OpenMagnetics::AdvancedCuk converter(converterJson);
|
|
511
|
+
converter._assertErrors = true;
|
|
512
|
+
if (useNgspice) {
|
|
513
|
+
auto designReqs = converter.process_design_requirements();
|
|
514
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
515
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(inductance);
|
|
516
|
+
OpenMagnetics::Inputs result;
|
|
517
|
+
result.set_design_requirements(designReqs);
|
|
518
|
+
result.set_operating_points(operatingPoints);
|
|
519
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::CUK_CONVERTER);
|
|
520
|
+
return result;
|
|
521
|
+
} else {
|
|
522
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
523
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::CUK_CONVERTER);
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
OpenMagnetics::Inputs process_sepic_internal(const json& converterJson, bool useNgspice) {
|
|
529
|
+
OpenMagnetics::AdvancedSepic converter(converterJson);
|
|
530
|
+
converter._assertErrors = true;
|
|
531
|
+
if (useNgspice) {
|
|
532
|
+
auto designReqs = converter.process_design_requirements();
|
|
533
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
534
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(inductance);
|
|
535
|
+
OpenMagnetics::Inputs result;
|
|
536
|
+
result.set_design_requirements(designReqs);
|
|
537
|
+
result.set_operating_points(operatingPoints);
|
|
538
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::SEPIC_CONVERTER);
|
|
539
|
+
return result;
|
|
540
|
+
} else {
|
|
541
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
542
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::SEPIC_CONVERTER);
|
|
543
|
+
return result;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
OpenMagnetics::Inputs process_zeta_internal(const json& converterJson, bool useNgspice) {
|
|
548
|
+
OpenMagnetics::AdvancedZeta converter(converterJson);
|
|
549
|
+
converter._assertErrors = true;
|
|
550
|
+
if (useNgspice) {
|
|
551
|
+
auto designReqs = converter.process_design_requirements();
|
|
552
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
553
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(inductance);
|
|
554
|
+
OpenMagnetics::Inputs result;
|
|
555
|
+
result.set_design_requirements(designReqs);
|
|
556
|
+
result.set_operating_points(operatingPoints);
|
|
557
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::ZETA_CONVERTER);
|
|
558
|
+
return result;
|
|
559
|
+
} else {
|
|
560
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
561
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::ZETA_CONVERTER);
|
|
562
|
+
return result;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
OpenMagnetics::Inputs process_four_switch_buck_boost_internal(const json& converterJson, bool useNgspice) {
|
|
567
|
+
OpenMagnetics::AdvancedFourSwitchBuckBoost converter(converterJson);
|
|
568
|
+
converter._assertErrors = true;
|
|
569
|
+
if (useNgspice) {
|
|
570
|
+
auto designReqs = converter.process_design_requirements();
|
|
571
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
572
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(inductance);
|
|
573
|
+
OpenMagnetics::Inputs result;
|
|
574
|
+
result.set_design_requirements(designReqs);
|
|
575
|
+
result.set_operating_points(operatingPoints);
|
|
576
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::FOUR_SWITCH_BUCK_BOOST_CONVERTER);
|
|
577
|
+
return result;
|
|
578
|
+
} else {
|
|
579
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
580
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::FOUR_SWITCH_BUCK_BOOST_CONVERTER);
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
OpenMagnetics::Inputs process_asymmetric_half_bridge_internal(const json& converterJson, bool useNgspice) {
|
|
586
|
+
OpenMagnetics::AdvancedAsymmetricHalfBridge converter(converterJson);
|
|
587
|
+
converter._assertErrors = true;
|
|
588
|
+
if (useNgspice) {
|
|
589
|
+
auto designReqs = converter.process_design_requirements();
|
|
590
|
+
std::vector<double> turnsRatios;
|
|
591
|
+
for (const auto& tr : designReqs.get_turns_ratios()) {
|
|
592
|
+
turnsRatios.push_back(OpenMagnetics::resolve_dimensional_values(tr));
|
|
593
|
+
}
|
|
594
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
595
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(turnsRatios, inductance);
|
|
596
|
+
OpenMagnetics::Inputs result;
|
|
597
|
+
result.set_design_requirements(designReqs);
|
|
598
|
+
result.set_operating_points(operatingPoints);
|
|
599
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::ASYMMETRIC_HALF_BRIDGE_CONVERTER);
|
|
600
|
+
return result;
|
|
601
|
+
} else {
|
|
602
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
603
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::ASYMMETRIC_HALF_BRIDGE_CONVERTER);
|
|
604
|
+
return result;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
OpenMagnetics::Inputs process_weinberg_internal(const json& converterJson, bool useNgspice) {
|
|
609
|
+
OpenMagnetics::AdvancedWeinberg converter(converterJson);
|
|
610
|
+
converter._assertErrors = true;
|
|
611
|
+
if (useNgspice) {
|
|
612
|
+
auto designReqs = converter.process_design_requirements();
|
|
613
|
+
std::vector<double> turnsRatios;
|
|
614
|
+
for (const auto& tr : designReqs.get_turns_ratios()) {
|
|
615
|
+
turnsRatios.push_back(OpenMagnetics::resolve_dimensional_values(tr));
|
|
616
|
+
}
|
|
617
|
+
if (turnsRatios.empty()) {
|
|
618
|
+
throw std::runtime_error("Weinberg converter requires at least one turns ratio");
|
|
619
|
+
}
|
|
620
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
621
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(turnsRatios[0], inductance);
|
|
622
|
+
OpenMagnetics::Inputs result;
|
|
623
|
+
result.set_design_requirements(designReqs);
|
|
624
|
+
result.set_operating_points(operatingPoints);
|
|
625
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::WEINBERG_CONVERTER);
|
|
626
|
+
return result;
|
|
627
|
+
} else {
|
|
628
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
629
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::WEINBERG_CONVERTER);
|
|
630
|
+
return result;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
OpenMagnetics::Inputs process_clllc_internal(const json& converterJson, bool useNgspice) {
|
|
635
|
+
OpenMagnetics::AdvancedClllc converter(converterJson);
|
|
636
|
+
converter._assertErrors = true;
|
|
637
|
+
if (useNgspice) {
|
|
638
|
+
auto designReqs = converter.process_design_requirements();
|
|
639
|
+
std::vector<double> turnsRatios;
|
|
640
|
+
for (const auto& tr : designReqs.get_turns_ratios()) {
|
|
641
|
+
turnsRatios.push_back(OpenMagnetics::resolve_dimensional_values(tr));
|
|
642
|
+
}
|
|
643
|
+
double inductance = OpenMagnetics::resolve_dimensional_values(designReqs.get_magnetizing_inductance());
|
|
644
|
+
auto operatingPoints = converter.simulate_and_extract_operating_points(turnsRatios, inductance);
|
|
645
|
+
OpenMagnetics::Inputs result;
|
|
646
|
+
result.set_design_requirements(designReqs);
|
|
647
|
+
result.set_operating_points(operatingPoints);
|
|
648
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::CLLLC_RESONANT_CONVERTER);
|
|
649
|
+
return result;
|
|
650
|
+
} else {
|
|
651
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
652
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::CLLLC_RESONANT_CONVERTER);
|
|
653
|
+
return result;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Vienna and Src follow the PFC pattern: AdvancedXxx overrides only
|
|
658
|
+
// process_design_requirements(); we invoke the inherited Topology::process()
|
|
659
|
+
// via the simple base class on the AdvancedXxx instance. useNgspice has
|
|
660
|
+
// no separate path here — process() already handles operating-point
|
|
661
|
+
// simulation through the topology pipeline.
|
|
662
|
+
OpenMagnetics::Inputs process_vienna_internal(const json& converterJson, bool useNgspice) {
|
|
663
|
+
(void)useNgspice;
|
|
664
|
+
OpenMagnetics::AdvancedVienna converter(converterJson);
|
|
665
|
+
converter._assertErrors = true;
|
|
666
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
667
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::VIENNA_RECTIFIER_CONVERTER);
|
|
668
|
+
return result;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
OpenMagnetics::Inputs process_src_internal(const json& converterJson, bool useNgspice) {
|
|
672
|
+
(void)useNgspice;
|
|
673
|
+
OpenMagnetics::AdvancedSrc converter(converterJson);
|
|
674
|
+
converter._assertErrors = true;
|
|
675
|
+
OpenMagnetics::Inputs result = converter.process();
|
|
676
|
+
result.get_mutable_design_requirements().set_topology(MAS::Topologies::SERIES_RESONANT_CONVERTER);
|
|
677
|
+
return result;
|
|
678
|
+
}
|
|
679
|
+
|
|
366
680
|
OpenMagnetics::Inputs dispatch_converter(const std::string& topologyName, const json& converterJson, bool useNgspice) {
|
|
367
681
|
if (topologyName == "flyback" || topologyName == "advanced_flyback") {
|
|
368
682
|
return process_flyback_internal(converterJson, useNgspice);
|
|
@@ -412,6 +726,33 @@ OpenMagnetics::Inputs dispatch_converter(const std::string& topologyName, const
|
|
|
412
726
|
else if (topologyName == "power_factor_correction" || topologyName == "pfc") {
|
|
413
727
|
return process_pfc_internal(converterJson);
|
|
414
728
|
}
|
|
729
|
+
else if (topologyName == "cuk" || topologyName == "advanced_cuk") {
|
|
730
|
+
return process_cuk_internal(converterJson, useNgspice);
|
|
731
|
+
}
|
|
732
|
+
else if (topologyName == "sepic" || topologyName == "advanced_sepic") {
|
|
733
|
+
return process_sepic_internal(converterJson, useNgspice);
|
|
734
|
+
}
|
|
735
|
+
else if (topologyName == "zeta" || topologyName == "advanced_zeta") {
|
|
736
|
+
return process_zeta_internal(converterJson, useNgspice);
|
|
737
|
+
}
|
|
738
|
+
else if (topologyName == "four_switch_buck_boost" || topologyName == "advanced_four_switch_buck_boost") {
|
|
739
|
+
return process_four_switch_buck_boost_internal(converterJson, useNgspice);
|
|
740
|
+
}
|
|
741
|
+
else if (topologyName == "asymmetric_half_bridge" || topologyName == "advanced_asymmetric_half_bridge") {
|
|
742
|
+
return process_asymmetric_half_bridge_internal(converterJson, useNgspice);
|
|
743
|
+
}
|
|
744
|
+
else if (topologyName == "weinberg" || topologyName == "advanced_weinberg") {
|
|
745
|
+
return process_weinberg_internal(converterJson, useNgspice);
|
|
746
|
+
}
|
|
747
|
+
else if (topologyName == "vienna" || topologyName == "advanced_vienna") {
|
|
748
|
+
return process_vienna_internal(converterJson, useNgspice);
|
|
749
|
+
}
|
|
750
|
+
else if (topologyName == "clllc" || topologyName == "advanced_clllc") {
|
|
751
|
+
return process_clllc_internal(converterJson, useNgspice);
|
|
752
|
+
}
|
|
753
|
+
else if (topologyName == "src" || topologyName == "advanced_src") {
|
|
754
|
+
return process_src_internal(converterJson, useNgspice);
|
|
755
|
+
}
|
|
415
756
|
else {
|
|
416
757
|
throw std::invalid_argument("Unknown topology: " + topologyName);
|
|
417
758
|
}
|
|
@@ -432,12 +773,18 @@ json process_converter_internal(const std::string& topologyName, const json& con
|
|
|
432
773
|
}
|
|
433
774
|
|
|
434
775
|
json process_converter(const std::string& topologyName, json converterJson, bool useNgspice) {
|
|
435
|
-
|
|
776
|
+
// Normalize topology name (accept MAS 1.0 camelCase, pre-1.0 Title Case,
|
|
777
|
+
// and the internal short form) and migrate any pre-1.0 enum strings
|
|
778
|
+
// embedded in the converter JSON (e.g. flyback "mode": "Continuous
|
|
779
|
+
// Conduction Mode" -> "continuousConductionMode") in-place.
|
|
780
|
+
std::string normalized = normalize_topology_name(topologyName);
|
|
781
|
+
OpenMagnetics::compat::migrate_pre_1_0(converterJson);
|
|
782
|
+
return process_converter_internal(normalized, converterJson, useNgspice);
|
|
436
783
|
}
|
|
437
784
|
|
|
438
785
|
// Simplified design_magnetics_from_converter using MKF template method
|
|
439
786
|
json design_magnetics_from_converter(
|
|
440
|
-
const std::string&
|
|
787
|
+
const std::string& topologyNameRaw,
|
|
441
788
|
json converterJson,
|
|
442
789
|
int maxResults,
|
|
443
790
|
json coreModeJson,
|
|
@@ -445,7 +792,11 @@ json design_magnetics_from_converter(
|
|
|
445
792
|
json weightsJson) {
|
|
446
793
|
|
|
447
794
|
(void)useNgspice; // Template method always uses ngspice
|
|
448
|
-
|
|
795
|
+
|
|
796
|
+
// Accept MAS 1.0 camelCase, pre-1.0 Title Case, or internal short form.
|
|
797
|
+
const std::string topologyName = normalize_topology_name(topologyNameRaw);
|
|
798
|
+
OpenMagnetics::compat::migrate_pre_1_0(converterJson);
|
|
799
|
+
|
|
449
800
|
try {
|
|
450
801
|
OpenMagnetics::CoreAdviser::CoreAdviserModes coreMode;
|
|
451
802
|
from_json(coreModeJson, coreMode);
|
|
@@ -535,6 +886,69 @@ json design_magnetics_from_converter(
|
|
|
535
886
|
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
536
887
|
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
537
888
|
}
|
|
889
|
+
else if (topologyName == "cuk" || topologyName == "advanced_cuk") {
|
|
890
|
+
OpenMagnetics::Cuk converter(converterJson);
|
|
891
|
+
converter._assertErrors = true;
|
|
892
|
+
masMagnetics = weights.empty()
|
|
893
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
894
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
895
|
+
}
|
|
896
|
+
else if (topologyName == "sepic" || topologyName == "advanced_sepic") {
|
|
897
|
+
OpenMagnetics::Sepic converter(converterJson);
|
|
898
|
+
converter._assertErrors = true;
|
|
899
|
+
masMagnetics = weights.empty()
|
|
900
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
901
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
902
|
+
}
|
|
903
|
+
else if (topologyName == "zeta" || topologyName == "advanced_zeta") {
|
|
904
|
+
OpenMagnetics::Zeta converter(converterJson);
|
|
905
|
+
converter._assertErrors = true;
|
|
906
|
+
masMagnetics = weights.empty()
|
|
907
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
908
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
909
|
+
}
|
|
910
|
+
else if (topologyName == "four_switch_buck_boost" || topologyName == "advanced_four_switch_buck_boost") {
|
|
911
|
+
OpenMagnetics::FourSwitchBuckBoost converter(converterJson);
|
|
912
|
+
converter._assertErrors = true;
|
|
913
|
+
masMagnetics = weights.empty()
|
|
914
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
915
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
916
|
+
}
|
|
917
|
+
else if (topologyName == "asymmetric_half_bridge" || topologyName == "advanced_asymmetric_half_bridge") {
|
|
918
|
+
OpenMagnetics::AsymmetricHalfBridge converter(converterJson);
|
|
919
|
+
converter._assertErrors = true;
|
|
920
|
+
masMagnetics = weights.empty()
|
|
921
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
922
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
923
|
+
}
|
|
924
|
+
else if (topologyName == "weinberg" || topologyName == "advanced_weinberg") {
|
|
925
|
+
OpenMagnetics::Weinberg converter(converterJson);
|
|
926
|
+
converter._assertErrors = true;
|
|
927
|
+
masMagnetics = weights.empty()
|
|
928
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
929
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
930
|
+
}
|
|
931
|
+
else if (topologyName == "vienna" || topologyName == "advanced_vienna") {
|
|
932
|
+
OpenMagnetics::Vienna converter(converterJson);
|
|
933
|
+
converter._assertErrors = true;
|
|
934
|
+
masMagnetics = weights.empty()
|
|
935
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
936
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
937
|
+
}
|
|
938
|
+
else if (topologyName == "clllc" || topologyName == "advanced_clllc") {
|
|
939
|
+
OpenMagnetics::Clllc converter(converterJson);
|
|
940
|
+
converter._assertErrors = true;
|
|
941
|
+
masMagnetics = weights.empty()
|
|
942
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
943
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
944
|
+
}
|
|
945
|
+
else if (topologyName == "src" || topologyName == "advanced_src") {
|
|
946
|
+
OpenMagnetics::Src converter(converterJson);
|
|
947
|
+
converter._assertErrors = true;
|
|
948
|
+
masMagnetics = weights.empty()
|
|
949
|
+
? magneticAdviser.get_advised_magnetic_from_converter(converter, maxResults)
|
|
950
|
+
: magneticAdviser.get_advised_magnetic_from_converter(converter, weights, maxResults);
|
|
951
|
+
}
|
|
538
952
|
else {
|
|
539
953
|
// Fall back to old approach for other topologies
|
|
540
954
|
json inputsJson = process_converter_internal(topologyName, converterJson, useNgspice);
|
|
@@ -629,6 +1043,16 @@ json process_current_transformer(json ctJson, double turnsRatio, double secondar
|
|
|
629
1043
|
return process_converter("current_transformer", ctJson, true);
|
|
630
1044
|
}
|
|
631
1045
|
|
|
1046
|
+
json process_cuk(json cukJson) { return process_converter("cuk", cukJson, true); }
|
|
1047
|
+
json process_sepic(json sepicJson) { return process_converter("sepic", sepicJson, true); }
|
|
1048
|
+
json process_zeta(json zetaJson) { return process_converter("zeta", zetaJson, true); }
|
|
1049
|
+
json process_four_switch_buck_boost(json j) { return process_converter("four_switch_buck_boost", j, true); }
|
|
1050
|
+
json process_asymmetric_half_bridge(json j) { return process_converter("asymmetric_half_bridge", j, true); }
|
|
1051
|
+
json process_weinberg(json j) { return process_converter("weinberg", j, true); }
|
|
1052
|
+
json process_vienna(json j) { return process_converter("vienna", j, true); }
|
|
1053
|
+
json process_clllc(json j) { return process_converter("clllc", j, true); }
|
|
1054
|
+
json process_src(json j) { return process_converter("src", j, true); }
|
|
1055
|
+
|
|
632
1056
|
// ─────────────────────────────────────────────────────────────────────
|
|
633
1057
|
// get_extra_components_inputs (MKF 2026-04-29 API)
|
|
634
1058
|
//
|
|
@@ -713,6 +1137,25 @@ dispatch_extra_components(const std::string& topologyName,
|
|
|
713
1137
|
return collect_extra_components<OpenMagnetics::IsolatedBuck>(converterJson, mode, magnetic);
|
|
714
1138
|
if (topologyName == "isolated_buck_boost")
|
|
715
1139
|
return collect_extra_components<OpenMagnetics::IsolatedBuckBoost>(converterJson, mode, magnetic);
|
|
1140
|
+
if (topologyName == "cuk" || topologyName == "advanced_cuk")
|
|
1141
|
+
return collect_extra_components<OpenMagnetics::Cuk>(converterJson, mode, magnetic);
|
|
1142
|
+
if (topologyName == "sepic" || topologyName == "advanced_sepic")
|
|
1143
|
+
return collect_extra_components<OpenMagnetics::Sepic>(converterJson, mode, magnetic);
|
|
1144
|
+
if (topologyName == "zeta" || topologyName == "advanced_zeta")
|
|
1145
|
+
return collect_extra_components<OpenMagnetics::Zeta>(converterJson, mode, magnetic);
|
|
1146
|
+
if (topologyName == "four_switch_buck_boost" || topologyName == "advanced_four_switch_buck_boost")
|
|
1147
|
+
return collect_extra_components<OpenMagnetics::FourSwitchBuckBoost>(converterJson, mode, magnetic);
|
|
1148
|
+
if (topologyName == "asymmetric_half_bridge" || topologyName == "advanced_asymmetric_half_bridge")
|
|
1149
|
+
return collect_extra_components<OpenMagnetics::AsymmetricHalfBridge>(converterJson, mode, magnetic);
|
|
1150
|
+
if (topologyName == "weinberg" || topologyName == "advanced_weinberg")
|
|
1151
|
+
return collect_extra_components<OpenMagnetics::Weinberg>(converterJson, mode, magnetic);
|
|
1152
|
+
if (topologyName == "clllc" || topologyName == "advanced_clllc")
|
|
1153
|
+
return collect_extra_components<OpenMagnetics::Clllc>(converterJson, mode, magnetic);
|
|
1154
|
+
if (topologyName == "src" || topologyName == "advanced_src")
|
|
1155
|
+
return collect_extra_components<OpenMagnetics::Src>(converterJson, mode, magnetic);
|
|
1156
|
+
// Vienna intentionally omitted: AdvancedVienna's MKF class does not
|
|
1157
|
+
// expose get_extra_components_inputs() — the rectifier brings no
|
|
1158
|
+
// detached design-requirement components beyond the boost inductor.
|
|
716
1159
|
throw std::invalid_argument(
|
|
717
1160
|
"get_extra_components_inputs: topology '" + topologyName +
|
|
718
1161
|
"' has no extra-components dispatch (or hasn't been wired in PyMKF)."
|
|
@@ -760,6 +1203,21 @@ std::string generate_spice_inductor(const json& converterJson,
|
|
|
760
1203
|
return topology.generate_ngspice_circuit(inductance, vinIdx, opIdx);
|
|
761
1204
|
}
|
|
762
1205
|
|
|
1206
|
+
// Isolated topologies with a single secondary winding (Weinberg): the
|
|
1207
|
+
// generate_ngspice_circuit signature takes a scalar turns ratio rather
|
|
1208
|
+
// than a vector. We pass turnsRatios[0] if available, otherwise 1.0.
|
|
1209
|
+
template <typename TopologyT>
|
|
1210
|
+
std::string generate_spice_isolated_scalar(const json& converterJson,
|
|
1211
|
+
const std::vector<double>& turnsRatios,
|
|
1212
|
+
double magnetizingInductance,
|
|
1213
|
+
size_t vinIdx, size_t opIdx) {
|
|
1214
|
+
TopologyT topology(converterJson);
|
|
1215
|
+
topology._assertErrors = true;
|
|
1216
|
+
topology.process();
|
|
1217
|
+
double turnsRatio = turnsRatios.empty() ? 1.0 : turnsRatios[0];
|
|
1218
|
+
return topology.generate_ngspice_circuit(turnsRatio, magnetizingInductance, vinIdx, opIdx);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
763
1221
|
} // namespace
|
|
764
1222
|
|
|
765
1223
|
json generate_ngspice_circuit(const std::string& topologyName,
|
|
@@ -793,6 +1251,27 @@ json generate_ngspice_circuit(const std::string& topologyName,
|
|
|
793
1251
|
else if (topologyName == "phase_shifted_half_bridge" || topologyName == "pshb") spice = generate_spice_isolated<OpenMagnetics::Pshb>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
794
1252
|
else if (topologyName == "isolated_buck") spice = generate_spice_isolated<OpenMagnetics::IsolatedBuck>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
795
1253
|
else if (topologyName == "isolated_buck_boost") spice = generate_spice_isolated<OpenMagnetics::IsolatedBuckBoost>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
1254
|
+
// Single-inductor non-isolated (2026-05): Cuk, Sepic, Zeta, FSBB.
|
|
1255
|
+
else if (topologyName == "cuk" || topologyName == "advanced_cuk")
|
|
1256
|
+
spice = generate_spice_inductor<OpenMagnetics::Cuk>(converterJson, magnetizingInductance, vinIdx, opIdx);
|
|
1257
|
+
else if (topologyName == "sepic" || topologyName == "advanced_sepic")
|
|
1258
|
+
spice = generate_spice_inductor<OpenMagnetics::Sepic>(converterJson, magnetizingInductance, vinIdx, opIdx);
|
|
1259
|
+
else if (topologyName == "zeta" || topologyName == "advanced_zeta")
|
|
1260
|
+
spice = generate_spice_inductor<OpenMagnetics::Zeta>(converterJson, magnetizingInductance, vinIdx, opIdx);
|
|
1261
|
+
else if (topologyName == "four_switch_buck_boost" || topologyName == "advanced_four_switch_buck_boost")
|
|
1262
|
+
spice = generate_spice_inductor<OpenMagnetics::FourSwitchBuckBoost>(converterJson, magnetizingInductance, vinIdx, opIdx);
|
|
1263
|
+
// Isolated with vector turns ratios (2026-05): AsymHB, Clllc, Src, Vienna.
|
|
1264
|
+
else if (topologyName == "asymmetric_half_bridge" || topologyName == "advanced_asymmetric_half_bridge")
|
|
1265
|
+
spice = generate_spice_isolated<OpenMagnetics::AsymmetricHalfBridge>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
1266
|
+
else if (topologyName == "clllc" || topologyName == "advanced_clllc")
|
|
1267
|
+
spice = generate_spice_isolated<OpenMagnetics::Clllc>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
1268
|
+
else if (topologyName == "src" || topologyName == "advanced_src")
|
|
1269
|
+
spice = generate_spice_isolated<OpenMagnetics::Src>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
1270
|
+
else if (topologyName == "vienna" || topologyName == "advanced_vienna")
|
|
1271
|
+
spice = generate_spice_isolated<OpenMagnetics::Vienna>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
1272
|
+
// Isolated with scalar turns ratio (single secondary): Weinberg.
|
|
1273
|
+
else if (topologyName == "weinberg" || topologyName == "advanced_weinberg")
|
|
1274
|
+
spice = generate_spice_isolated_scalar<OpenMagnetics::Weinberg>(converterJson, turnsRatios, magnetizingInductance, vinIdx, opIdx);
|
|
796
1275
|
else return json{{"error", "generate_ngspice_circuit: unknown topology '" + topologyName + "'"}};
|
|
797
1276
|
return json{{"netlist", spice}};
|
|
798
1277
|
} catch (const std::exception& exc) {
|
|
@@ -866,6 +1345,19 @@ void register_converter_bindings(py::module& m) {
|
|
|
866
1345
|
m.def("process_current_transformer", &process_current_transformer, "Process Current Transformer.",
|
|
867
1346
|
py::arg("ct"), py::arg("turns_ratio"), py::arg("secondary_resistance") = 0.0);
|
|
868
1347
|
|
|
1348
|
+
// 2026-05 additions: full coverage of MKF's 24 converter topologies.
|
|
1349
|
+
m.def("process_cuk", &process_cuk, "Process Cuk converter.", py::arg("cuk"));
|
|
1350
|
+
m.def("process_sepic", &process_sepic, "Process SEPIC converter.", py::arg("sepic"));
|
|
1351
|
+
m.def("process_zeta", &process_zeta, "Process Zeta converter.", py::arg("zeta"));
|
|
1352
|
+
m.def("process_four_switch_buck_boost", &process_four_switch_buck_boost,
|
|
1353
|
+
"Process Four-Switch Buck-Boost converter.", py::arg("converter"));
|
|
1354
|
+
m.def("process_asymmetric_half_bridge", &process_asymmetric_half_bridge,
|
|
1355
|
+
"Process Asymmetric Half-Bridge converter.", py::arg("converter"));
|
|
1356
|
+
m.def("process_weinberg", &process_weinberg, "Process Weinberg converter.", py::arg("converter"));
|
|
1357
|
+
m.def("process_vienna", &process_vienna, "Process Vienna Rectifier converter.", py::arg("converter"));
|
|
1358
|
+
m.def("process_clllc", &process_clllc, "Process CLLLC Resonant converter.", py::arg("converter"));
|
|
1359
|
+
m.def("process_src", &process_src, "Process Series Resonant converter (SRC).", py::arg("converter"));
|
|
1360
|
+
|
|
869
1361
|
m.def("generate_ngspice_circuit", &generate_ngspice_circuit,
|
|
870
1362
|
"Return the canonical ngspice SPICE deck for the topology at a "
|
|
871
1363
|
"given operating point, sized from the magnetic design (turns "
|
|
@@ -28,6 +28,17 @@ json process_isolated_buck(json isolatedBuckJson);
|
|
|
28
28
|
json process_isolated_buck_boost(json isolatedBuckBoostJson);
|
|
29
29
|
json process_current_transformer(json ctJson, double turnsRatio, double secondaryResistance = 0.0);
|
|
30
30
|
|
|
31
|
+
// 2026-05 additions: full coverage of MKF's 24 converter topologies.
|
|
32
|
+
json process_cuk(json cukJson);
|
|
33
|
+
json process_sepic(json sepicJson);
|
|
34
|
+
json process_zeta(json zetaJson);
|
|
35
|
+
json process_four_switch_buck_boost(json converterJson);
|
|
36
|
+
json process_asymmetric_half_bridge(json converterJson);
|
|
37
|
+
json process_weinberg(json converterJson);
|
|
38
|
+
json process_vienna(json converterJson);
|
|
39
|
+
json process_clllc(json converterJson);
|
|
40
|
+
json process_src(json converterJson);
|
|
41
|
+
|
|
31
42
|
void register_converter_bindings(py::module& m);
|
|
32
43
|
|
|
33
44
|
} // namespace PyMKF
|
|
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
|
|
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
|