@@ -20,6 +20,80 @@ using namespace MAS;
2020
2121namespace OpenMagnetics {
2222
23+ /* *
24+ * @class CoreAdviser
25+ * @brief Multi-criteria magnetic core recommendation system.
26+ *
27+ * ## Overview
28+ * CoreAdviser selects optimal magnetic cores for power electronics applications based on
29+ * user-defined priorities. It evaluates cores from a database using multiple criteria and
30+ * returns ranked recommendations with normalized scores.
31+ *
32+ * ## Scoring System
33+ * The adviser uses three main filter categories, each with configurable weights (0.0-1.0):
34+ * - **COST**: Estimated manufacturing/purchasing cost (lower is better)
35+ * - **EFFICIENCY**: Power losses (core + DC winding losses, lower is better)
36+ * - **DIMENSIONS**: Physical size/volume (smaller is better)
37+ *
38+ * ### Score Calculation
39+ * 1. Each filter computes a raw score for each core candidate
40+ * 2. Scores are normalized using `normalize_scoring()`:
41+ * - `invert=true`: Lower raw values get higher scores (used for cost, losses, size)
42+ * - `log=true`: Logarithmic normalization (compresses large differences)
43+ * - `log=false`: Linear normalization (preserves proportional differences)
44+ * 3. Final score = Σ(normalized_score × weight) for all filters
45+ *
46+ * ## Filter Pipeline
47+ *
48+ * ### Power Application (filter_available_cores_power_application)
49+ * The filter chain for power inductors/transformers:
50+ * 1. **filterAreaProduct**: Pre-filter using Area Product (AP = Aw × Ac)
51+ * - Fixed weight 1.0 (binary pass/fail, not scored)
52+ * - Eliminates cores too small for required energy storage
53+ * 2. **filterEnergyStored**: Validates energy storage capacity (L×I²/2)
54+ * - Fixed weight 1.0 (binary pass/fail, not scored)
55+ * - Checks if core can store required energy without saturation
56+ * 3. **filterCost**: Scores by estimated cost
57+ * - Weight: COST user weight
58+ * 4. **filterDimensions**: Scores by physical volume
59+ * - Weight: DIMENSIONS user weight
60+ * - Uses linear normalization to preserve size differences
61+ * 5. **filterLosses**: Scores by total losses (core + winding DC)
62+ * - Weight: EFFICIENCY user weight
63+ *
64+ * ### Suppression Application (filter_available_cores_suppression_application)
65+ * The filter chain for EMI/RFI suppression:
66+ * 1. **filterMinimumImpedance**: Pre-filter by impedance at operating frequency
67+ * 2. **filterCost**: Scores by estimated cost
68+ * 3. **filterDimensions**: Scores by physical volume
69+ * 4. **filterMagneticInductance**: Scores by magnetizing inductance
70+ * 5. **filterLosses**: Scores by total losses
71+ *
72+ * ## Operating Modes
73+ * - **AVAILABLE_CORES**: Uses manufacturer stock database (fastest)
74+ * - **STANDARD_CORES**: Uses standard core shapes with material optimization
75+ * - **CUSTOM_CORES**: Uses user-provided core list
76+ *
77+ * ## Toroid Handling
78+ * Toroidal cores use geometry-based bobbin filling factor calculation:
79+ * fillingFactor = 0.55 + 0.15 × (innerRadius / outerRadius)
80+ * This accounts for the reduced winding area in toroid centers (range: 0.55-0.70).
81+ *
82+ * ## Usage Example
83+ * ```cpp
84+ * std::map<CoreAdviserFilters, double> weights = {
85+ * {CoreAdviserFilters::COST, 0.3},
86+ * {CoreAdviserFilters::EFFICIENCY, 0.5},
87+ * {CoreAdviserFilters::DIMENSIONS, 0.2}
88+ * };
89+ * CoreAdviser adviser;
90+ * auto results = adviser.get_advised_core(inputs, weights, 5); // Top 5 cores
91+ * ```
92+ *
93+ * ## References
94+ * - Industry practice: LI² (energy storage), Area Product method
95+ * - Colonel Wm. T. McLyman, "Transformer and Inductor Design Handbook"
96+ */
2397class CoreAdviser {
2498 public:
2599 enum class CoreAdviserFilters : int {
@@ -45,6 +119,21 @@ class CoreAdviser {
45119
46120 public:
47121
122+ /* *
123+ * @brief Filter normalization configuration for each scoring category.
124+ *
125+ * Each filter category has two configuration options:
126+ * - **invert**: If true, lower raw values result in higher normalized scores.
127+ * Used when "less is better" (cost, losses, size).
128+ * - **log**: If true, uses logarithmic normalization; if false, linear.
129+ * Linear normalization preserves proportional differences between cores.
130+ *
131+ * Configuration rationale:
132+ * - COST: inverted (cheaper=better), logarithmic (diminishing returns on savings)
133+ * - EFFICIENCY: inverted (lower losses=better), logarithmic (diminishing returns)
134+ * - DIMENSIONS: inverted (smaller=better), LINEAR (size differences should be
135+ * proportionally reflected; a core 2× larger should score proportionally worse)
136+ */
48137 std::map<CoreAdviserFilters, std::map<std::string, bool >> _filterConfiguration{
49138 { CoreAdviserFilters::COST, { {" invert" , true }, {" log" , true } } },
50139 { CoreAdviserFilters::EFFICIENCY, { {" invert" , true }, {" log" , true } } },
@@ -63,6 +152,11 @@ class CoreAdviser {
63152 _models[" coreLosses" ] = to_string (defaults.coreLossesModelDefault );
64153 _models[" coreTemperature" ] = to_string (defaults.coreTemperatureModelDefault );
65154 }
155+ /* *
156+ * @brief Get per-core scoring breakdown for debugging/analysis.
157+ * @param weighted If true, returns weighted scores; otherwise raw normalized scores.
158+ * @return Map of core names to their per-filter scores.
159+ */
66160 std::map<std::string, std::map<CoreAdviserFilters, double >> get_scorings (bool weighted = false );
67161
68162 void set_unique_core_shapes (bool value);
@@ -72,7 +166,21 @@ class CoreAdviser {
72166 void set_mode (CoreAdviserModes value);
73167 CoreAdviserModes get_mode ();
74168
169+ /* *
170+ * @brief Main entry point for core recommendation.
171+ * @param inputs Operating conditions (voltage, current, frequency, etc.)
172+ * @param maximumNumberResults Maximum number of cores to return.
173+ * @return Vector of (Mas, score) pairs, sorted by descending score.
174+ */
75175 std::vector<std::pair<Mas, double >> get_advised_core (Inputs inputs, size_t maximumNumberResults=1 );
176+
177+ /* *
178+ * @brief Core recommendation with custom weights.
179+ * @param inputs Operating conditions.
180+ * @param weights Map of filter weights (COST, EFFICIENCY, DIMENSIONS). Values 0.0-1.0.
181+ * @param maximumNumberResults Maximum number of cores to return.
182+ * @return Vector of (Mas, score) pairs, sorted by descending score.
183+ */
76184 std::vector<std::pair<Mas, double >> get_advised_core (Inputs inputs, std::map<CoreAdviserFilters, double > weights, size_t maximumNumberResults=1 );
77185 std::vector<std::pair<Mas, double >> get_advised_core (Inputs inputs, std::vector<Core>* cores, size_t maximumNumberResults=1 );
78186 std::vector<std::pair<Mas, double >> get_advised_core (Inputs inputs, std::map<CoreAdviserFilters, double > weights, std::vector<Core>* cores, size_t maximumNumberResults=1 );
@@ -81,10 +189,49 @@ class CoreAdviser {
81189 std::vector<std::pair<Mas, double >> get_advised_core (Inputs inputs, std::vector<CoreShape>* shapes, size_t maximumNumberResults=1 );
82190
83191 Mas post_process_core (Magnetic magnetic, Inputs inputs);
192+
193+ /* *
194+ * @brief Filter pipeline for power inductor/transformer applications.
195+ *
196+ * Applies filters in order: AreaProduct → EnergyStored → Cost → Dimensions → Losses.
197+ * - AreaProduct and EnergyStored use fixed weight 1.0 (pre-filtering, not scoring)
198+ * - Cost, Dimensions, Losses use user-provided weights for scoring
199+ *
200+ * @param magnetics Input list of candidate magnetics with initial scores.
201+ * @param inputs Operating conditions.
202+ * @param weights User-defined weights for COST, EFFICIENCY, DIMENSIONS.
203+ * @param maximumMagneticsAfterFiltering Max candidates to keep after filtering.
204+ * @param maximumNumberResults Max results to return.
205+ * @return Filtered and scored list of (Mas, score) pairs.
206+ */
84207 std::vector<std::pair<Mas, double >> filter_available_cores_power_application (std::vector<std::pair<Magnetic, double >>* magnetics, Inputs inputs, std::map<CoreAdviserFilters, double > weights, size_t maximumMagneticsAfterFiltering, size_t maximumNumberResults);
208+
209+ /* *
210+ * @brief Filter pipeline for EMI/RFI suppression applications.
211+ *
212+ * Applies filters: MinimumImpedance → Cost → Dimensions → MagneticInductance → Losses.
213+ *
214+ * @param magnetics Input list of candidate magnetics with initial scores.
215+ * @param inputs Operating conditions (includes required impedance at frequency).
216+ * @param weights User-defined weights for COST, EFFICIENCY, DIMENSIONS.
217+ * @param maximumMagneticsAfterFiltering Max candidates to keep after filtering.
218+ * @param maximumNumberResults Max results to return.
219+ * @return Filtered and scored list of (Mas, score) pairs.
220+ */
85221 std::vector<std::pair<Mas, double >> filter_available_cores_suppression_application (std::vector<std::pair<Magnetic, double >>* magnetics, Inputs inputs, std::map<CoreAdviserFilters, double > weights, size_t maximumMagneticsAfterFiltering, size_t maximumNumberResults);
86- std::vector<std::pair<Mas, double >> filter_standard_cores_power_application (std::vector<std::pair<Magnetic, double >>* magnetics, Inputs inputs, size_t maximumMagneticsAfterFiltering, size_t maximumNumberResults);
87- std::vector<std::pair<Mas, double >> filter_standard_cores_interference_suppression_application (std::vector<std::pair<Magnetic, double >>* magnetics, Inputs inputs, size_t maximumMagneticsAfterFiltering, size_t maximumNumberResults);
222+
223+ /* *
224+ * @brief Filter pipeline for standard core shapes (with material selection).
225+ *
226+ * Similar to filter_available_cores_power_application but works with
227+ * parametric core shapes rather than specific stock cores.
228+ */
229+ std::vector<std::pair<Mas, double >> filter_standard_cores_power_application (std::vector<std::pair<Magnetic, double >>* magnetics, Inputs inputs, std::map<CoreAdviserFilters, double > weights, size_t maximumMagneticsAfterFiltering, size_t maximumNumberResults);
230+
231+ /* *
232+ * @brief Filter pipeline for standard core shapes in suppression applications.
233+ */
234+ std::vector<std::pair<Mas, double >> filter_standard_cores_interference_suppression_application (std::vector<std::pair<Magnetic, double >>* magnetics, Inputs inputs, std::map<CoreAdviserFilters, double > weights, size_t maximumMagneticsAfterFiltering, size_t maximumNumberResults);
88235 std::vector<std::pair<Magnetic, double >> create_magnetic_dataset (Inputs inputs, std::vector<Core>* cores, bool includeStacks);
89236 std::vector<std::pair<Magnetic, double >> create_magnetic_dataset (Inputs inputs, std::vector<CoreShape>* shapes, bool includeStacks);
90237 void expand_magnetic_dataset_with_stacks (Inputs inputs, std::vector<Core>* cores, std::vector<std::pair<Magnetic, double >>* magnetics);
0 commit comments