Skip to content

Commit 9196f87

Browse files
committed
feat: Pass OperatingPoint to StrayCapacitance for proper voltage scaling
Add new calculate_capacitance(Coil, OperatingPoint) overload that extracts actual RMS voltages from the operating point excitations. This enables correct electric field visualization with actual operating voltages instead of hardcoded 10V reference. Changes: - Add calculate_capacitance(Coil, OperatingPoint) with validation - Extract RMS voltages from winding excitations with exception handling - Add private helper calculate_capacitance_with_voltages() for shared logic - Update calculate_electric_field_sdf() to pass operating point - Update test to use SDF_PHYSICS model for electric field visualization The electric field now properly scales with actual operating voltage (~676V RMS) showing visible color variation from blue (low) to red/yellow (high field intensity).
1 parent e45471a commit 9196f87

4 files changed

Lines changed: 71 additions & 10 deletions

File tree

‎src/physical_models/StrayCapacitance.cpp‎

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,46 @@ std::pair<SixCapacitorNetworkPerWinding, TripoleCapacitancePerWinding> StrayCapa
14521452

14531453

14541454
StrayCapacitanceOutput StrayCapacitance::calculate_capacitance(Coil coil) {
1455+
std::map<std::string, double> voltageRmsPerWinding;
1456+
double primaryNumberTurns = coil.get_functional_description()[0].get_number_turns();
1457+
for (auto winding : coil.get_functional_description()) {
1458+
double turnsRatio = primaryNumberTurns / winding.get_number_turns();
1459+
voltageRmsPerWinding[winding.get_name()] = 10.0 / turnsRatio;
1460+
}
1461+
return calculate_capacitance_with_voltages(coil, voltageRmsPerWinding);
1462+
}
1463+
1464+
StrayCapacitanceOutput StrayCapacitance::calculate_capacitance(Coil coil, OperatingPoint operatingPoint) {
1465+
// Extract actual RMS voltages from operating point
1466+
std::map<std::string, double> voltageRmsPerWinding;
1467+
1468+
for (size_t windingIndex = 0; windingIndex < coil.get_functional_description().size(); ++windingIndex) {
1469+
if (windingIndex >= operatingPoint.get_excitations_per_winding().size()) {
1470+
throw InvalidInputException(ErrorCode::MISSING_DATA, "Missing excitation for winding index: " + std::to_string(windingIndex));
1471+
}
1472+
1473+
auto& excitation = operatingPoint.get_excitations_per_winding()[windingIndex];
1474+
1475+
if (!excitation.get_voltage()) {
1476+
throw InvalidInputException(ErrorCode::MISSING_DATA, "Missing voltage in excitation for winding: " + coil.get_functional_description()[windingIndex].get_name());
1477+
}
1478+
1479+
if (!excitation.get_voltage()->get_processed()) {
1480+
throw InvalidInputException(ErrorCode::MISSING_DATA, "Voltage is not processed for winding: " + coil.get_functional_description()[windingIndex].get_name());
1481+
}
1482+
1483+
auto rmsVoltage = excitation.get_voltage()->get_processed()->get_rms();
1484+
if (!rmsVoltage) {
1485+
throw InvalidInputException(ErrorCode::MISSING_DATA, "Missing RMS voltage value for winding: " + coil.get_functional_description()[windingIndex].get_name());
1486+
}
1487+
1488+
voltageRmsPerWinding[coil.get_functional_description()[windingIndex].get_name()] = rmsVoltage.value();
1489+
}
1490+
1491+
return calculate_capacitance_with_voltages(coil, voltageRmsPerWinding);
1492+
}
1493+
1494+
StrayCapacitanceOutput StrayCapacitance::calculate_capacitance_with_voltages(Coil coil, std::map<std::string, double> voltageRmsPerWinding) {
14551495
std::map<std::pair<size_t, size_t>, double> electricEnergyBetweenTurnsMap;
14561496
std::map<std::pair<size_t, size_t>, double> voltageDropBetweenTurnsMap;
14571497
std::map<std::string, std::map<std::string, ScalarMatrixAtFrequency>> capacitanceMatrix;
@@ -1460,13 +1500,6 @@ StrayCapacitanceOutput StrayCapacitance::calculate_capacitance(Coil coil) {
14601500

14611501
auto capacitanceAmongTurns = calculate_capacitance_among_turns(coil);
14621502

1463-
std::map<std::string, double> voltageRmsPerWinding;
1464-
double primaryNumberTurns = coil.get_functional_description()[0].get_number_turns();
1465-
for (auto winding : coil.get_functional_description()) {
1466-
double turnsRatio = primaryNumberTurns / winding.get_number_turns();
1467-
voltageRmsPerWinding[winding.get_name()] = 10.0 / turnsRatio;
1468-
}
1469-
14701503
auto strayCapacitanceOutput = StrayCapacitance::calculate_voltages_per_turn(coil, voltageRmsPerWinding);
14711504
auto voltagesPerTurn = strayCapacitanceOutput.get_voltage_per_turn().value();
14721505
auto windings = coil.get_functional_description();

‎src/physical_models/StrayCapacitance.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class StrayCapacitance{
7272
StrayCapacitanceModels _modelName;
7373
static double calculate_area_between_two_turns_using_diagonals(Turn firstTurn, Turn secondTurn);
7474
static double calculate_area_between_two_turns_using_vecticals_and_horizontals(Turn firstTurn, Turn secondTurn);
75+
StrayCapacitanceOutput calculate_capacitance_with_voltages(Coil coil, std::map<std::string, double> voltageRmsPerWinding);
7576
public:
7677

7778
StrayCapacitance(StrayCapacitanceModels strayCapacitanceModel = StrayCapacitanceModels::ALBACH){
@@ -93,6 +94,7 @@ class StrayCapacitance{
9394
std::map<std::pair<size_t, size_t>, double> calculate_capacitance_among_turns(Coil coil);
9495

9596
StrayCapacitanceOutput calculate_capacitance(Coil coil);
97+
StrayCapacitanceOutput calculate_capacitance(Coil coil, OperatingPoint operatingPoint);
9698

9799
// Bipolar coordinate system for round-round energy density computation
98100
struct BipolarParams {

‎src/support/Painter.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ Field PainterInterface::calculate_electric_field_sdf(OperatingPoint operatingPoi
474474
size_t numberPointsY = settings.get_painter_number_points_y();
475475
Field inducedField = CoilMesher::generate_mesh_induced_grid(magnetic, frequency, numberPointsX, numberPointsY, false, false).first;
476476

477-
auto capacitanceOutput = strayCapacitance.calculate_capacitance(coil);
477+
auto capacitanceOutput = strayCapacitance.calculate_capacitance(coil, operatingPoint);
478478
auto voltageDropAmongTurnsOpt = capacitanceOutput.get_voltage_drop_among_turns();
479479
if (!voltageDropAmongTurnsOpt) {
480480
// Return the mesh field even without voltage data

‎tests/TestCoilAdviser.cpp‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "advisers/CoreAdviser.h"
77
#include "advisers/CoilAdviser.h"
88
#include "processors/Inputs.h"
9+
#include "physical_models/StrayCapacitance.h"
910
#include <magic_enum.hpp>
1011
#include "TestingUtils.h"
1112
#include "support/Settings.h"
@@ -2173,6 +2174,28 @@ TEST_CASE("Test_CoilAdviser_WASM_Replication", "[adviser][coil-adviser][wasm-rep
21732174
REQUIRE(currentDensity < 12e6);
21742175
}
21752176

2177+
// Calculate voltage for each winding (needed for electric field calculation)
2178+
// Get the actual magnetizing inductance from the designed magnetic
2179+
auto magnetic = masMagneticsWithCoil[0].get_mutable_magnetic();
2180+
OpenMagnetics::MagnetizingInductance magnetizingInductanceModel("ZHANG");
2181+
2182+
// Add voltage to each winding's excitation
2183+
for (size_t opIndex = 0; opIndex < masMagneticsWithCoil[0].get_inputs().get_operating_points().size(); ++opIndex) {
2184+
auto& operatingPoint = masMagneticsWithCoil[0].get_mutable_inputs().get_mutable_operating_points()[opIndex];
2185+
auto inductanceOutput = magnetizingInductanceModel.calculate_inductance_from_number_turns_and_gapping(
2186+
magnetic.get_mutable_core(), coil, &operatingPoint);
2187+
double magnetizingInductance = resolve_dimensional_values(inductanceOutput.get_magnetizing_inductance());
2188+
2189+
for (size_t windingIndex = 0; windingIndex < magnetic.get_coil().get_functional_description().size(); ++windingIndex) {
2190+
auto& excitation = operatingPoint.get_mutable_excitations_per_winding()[windingIndex];
2191+
// Calculate induced voltage based on turns ratio
2192+
double turnsRatio = static_cast<double>(coil.get_functional_description()[windingIndex].get_number_turns()) / static_cast<double>(coil.get_functional_description()[0].get_number_turns());
2193+
double windingInductance = magnetizingInductance * pow(turnsRatio, 2);
2194+
auto voltage = OpenMagnetics::Inputs::calculate_induced_voltage(excitation, windingInductance);
2195+
excitation.set_voltage(voltage);
2196+
}
2197+
}
2198+
21762199
auto outputFilePath = std::filesystem::path{ std::source_location::current().file_name() }.parent_path().append("..").append("output");
21772200
auto outFile = outputFilePath;
21782201
std::string filename = "Test_CoilAdviser_WASM_Replication.svg";
@@ -2184,9 +2207,12 @@ TEST_CASE("Test_CoilAdviser_WASM_Replication", "[adviser][coil-adviser][wasm-rep
21842207
OpenMagnetics::Settings::GetInstance().set_painter_number_points_y(100);
21852208
OpenMagnetics::Settings::GetInstance().set_painter_include_fringing(false);
21862209

2187-
// Paint electric field using the first operating point
2210+
// Paint electric field using the first operating point with SDF_PHYSICS model
21882211
painter.paint_electric_field(masMagneticsWithCoil[0].get_inputs().get_operating_points()[0],
2189-
masMagneticsWithCoil[0].get_magnetic());
2212+
masMagneticsWithCoil[0].get_magnetic(),
2213+
1, std::nullopt,
2214+
ElectricFieldVisualizationModel::SDF_PHYSICS,
2215+
ColorPalette::VIRIDIS);
21902216

21912217
painter.paint_core(masMagneticsWithCoil[0].get_mutable_magnetic());
21922218
painter.paint_bobbin(masMagneticsWithCoil[0].get_mutable_magnetic());

0 commit comments

Comments
 (0)