diff --git a/src/Circuit.jsx b/src/Circuit.jsx index b5e4184..adba9cc 100644 --- a/src/Circuit.jsx +++ b/src/Circuit.jsx @@ -534,50 +534,99 @@ function ComplexComponent({ real, imaginary, index, setUserCircuit, slider_re, s ); } -function TransformerComponent({ l1, unit_l1, l2, unit_l2, k, index, setUserCircuit }) { +function TransformerComponent({ l1, unit_l1, l2, unit_l2, k, model, index, setUserCircuit }) { + const modelValue = model ?? "coupledInductor"; return ( <> ~ - - setValue(e.target.value, "l1", setUserCircuit, index)} + setUnit(e.target.value, "model", setUserCircuit, index)} + sx={{ m: 0, mb: 1, p: 0, alignItems: "center", minHeight: 60, "& .MuiFormControlLabel-root": { margin: 0 } }} + > + } + label="Coupled-Inductor Model" + sx={{ "& .MuiFormControlLabel-label": { fontSize: "0.7rem", lineHeight: 1 }, my: 0, mr: 1 }} /> - - - - setValue(e.target.value, "l2", setUserCircuit, index)} + } + label="Ideal Transformer" + sx={{ "& .MuiFormControlLabel-label": { fontSize: "0.7rem", lineHeight: 1 }, my: 0 }} /> - - - setValue(e.target.value, "k", setUserCircuit, index)} - /> + + {modelValue === "coupledInductor" && ( + <> + + setValue(e.target.value, "l1", setUserCircuit, index)} + /> + + + + setValue(e.target.value, "l2", setUserCircuit, index)} + /> + + + setValue(e.target.value, "k", setUserCircuit, index)} + /> + + )} + {modelValue === "ideal" && ( + + + 1 : + + setValue(e.target.value, "k", setUserCircuit, index)} + /> + + )} ); } @@ -920,6 +969,7 @@ function Circuit({ userCircuit, setUserCircuit, frequency, setPlotType, setSetti l2={component.l2} unit_l2={component.unit_l2} k={component.k} + model={component.model} index={index} setUserCircuit={setUserCircuit} key={type} diff --git a/src/circuitComponents.js b/src/circuitComponents.js index bbefeee..802b912 100644 --- a/src/circuitComponents.js +++ b/src/circuitComponents.js @@ -356,8 +356,8 @@ export const circuitComponents = { name: "Transformer", src: transformer, circuitInputs: ["transformer"], - default: { l1: 1, unit_l1: "nH", l2: 1, unit_l2: "nH", k: 1 }, - toURL: (c) => `transformer_${c.l1}_${c.unit_l1}_${c.l2}_${c.unit_l2}_${c.k}`, + default: { l1: 1, unit_l1: "nH", l2: 1, unit_l2: "nH", k: 1, model: "coupledInductor" }, + toURL: (c) => `transformer_${c.l1}_${c.unit_l1}_${c.l2}_${c.unit_l2}_${c.k}_${c.model ?? "coupledInductor"}`, fromURL: (u) => { return { name: u[0], @@ -366,6 +366,7 @@ export const circuitComponents = { l2: Number(u[3]), unit_l2: u[4], k: Number(u[5]), + model: u[6] === "ideal" ? "ideal" : "coupledInductor", }; }, }, diff --git a/src/impedanceFunctions.js b/src/impedanceFunctions.js index 34f20e5..3c38281 100644 --- a/src/impedanceFunctions.js +++ b/src/impedanceFunctions.js @@ -151,30 +151,44 @@ export function calculateImpedance(userCircuit, frequency, resolution, showIdeal line_length = ((lengthLambda % 0.5) * speedOfLight) / frequency; calculateTlineZ(resolution, component, line_length, beta, startImaginary, startReal, impedanceResolution, startAdmittance); } else if (component.name == "transformer") { - //coupled inductor model. Do 3 separate equations - // --- L1 --- --- L2 --- <- look this way - // | | - // Zo Lm - // | | - var l1w = w * component.l1 * unitConverter[component.unit_l1]; - var l2w = w * component.l2 * unitConverter[component.unit_l2]; - var lmw = component.k * Math.sqrt(l1w * l2w); - var i1z, i2z, newStartAdmittance; - - for (j = 0; j <= resolution; j++) { - //L1 - i1z = { - real: startReal, - imaginary: startImaginary + ((l1w - lmw) * j) / resolution, - }; - //Lm - newStartAdmittance = one_over_complex(i1z); - i2z = one_over_complex({ real: newStartAdmittance.real, imaginary: newStartAdmittance.imaginary - ((1 / lmw) * j) / resolution }); - //L2 - impedanceResolution.push({ - real: i2z.real, - imaginary: i2z.imaginary + ((l2w - lmw) * j) / resolution, - }); + if (component.model === "ideal") { + // Ideal transformer: Z_out = n² * Z_in (turns ratio n from primary to secondary) + var n = Number(component.k); + if (isNaN(n) || n <= 0) n = 1; + var n2 = n * n; + for (j = 0; j <= resolution; j++) { + const transformerScaler = 1 + ((n2 - 1) * j) / resolution; + impedanceResolution.push({ + real: transformerScaler * startReal, + imaginary: transformerScaler * startImaginary, + }); + } + } else { + // Coupled inductor model. Do 3 separate equations + // --- L1 --- --- L2 --- <- look this way + // | | + // Zo Lm + // | | + var l1w = w * component.l1 * unitConverter[component.unit_l1]; + var l2w = w * component.l2 * unitConverter[component.unit_l2]; + var lmw = component.k * Math.sqrt(l1w * l2w); + var i1z, i2z, newStartAdmittance; + + for (j = 0; j <= resolution; j++) { + //L1 + i1z = { + real: startReal, + imaginary: startImaginary + ((l1w - lmw) * j) / resolution, + }; + //Lm + newStartAdmittance = one_over_complex(i1z); + i2z = one_over_complex({ real: newStartAdmittance.real, imaginary: newStartAdmittance.imaginary - ((1 / lmw) * j) / resolution }); + //L2 + impedanceResolution.push({ + real: i2z.real, + imaginary: i2z.imaginary + ((l2w - lmw) * j) / resolution, + }); + } } } else if (component.name == "custom") { newImpedance = CustomZAtFrequency(component.value, frequency, component.interpolation); diff --git a/tests/impedance.test.js b/tests/impedance.test.js index 2d1fcf8..536f5b8 100644 --- a/tests/impedance.test.js +++ b/tests/impedance.test.js @@ -129,6 +129,105 @@ test("Cap with ESL and ESR", () => { }); }); +test("Ideal Transformer", () => { + const circuit = [ + { + name: "blackBox", + real: "20", + imaginary: "20", + tolerance: 0, + }, + { + name: "transformer", + l1: 2, + unit_l1: "nH", + l2: 1, + unit_l2: "nH", + k: 2.04, + model: "ideal", + }, + ]; + const settings = { + zo: 50, + frequency: 2440, + frequencyUnit: "MHz", + fSpan: 0, + fSpanUnit: "MHz", + fRes: 10, + zMarkers: [], + vswrCircles: [], + qCircles: [], + nfCircles: [], + gainInCircles: [], + gainOutCircles: [], + }; + const [processedImpedanceResults, _spanResults, _multiZResults, _gainArray, _noiseArray, _numericalFrequency, _RefIn] = allImpedanceCalculations( + circuit, + settings, + ); + + expect(processedImpedanceResults).toEqual({ + zStr: "83.23 + 83.23j", + zPolarStr: "117.71 ∠ 45.00°", + refStr: "0.460 + 0.337j", + refPolarStr: "0.570 ∠ 36.2°", + vswr: "3.66", + qFactor: "1.00", + refReal: 0.46012557939346155, + refImag: 0.33726753164347456, + admString: "0.00601 - 0.00601j", + }); +}); + +test("Coupled Transformer", () => { + const circuit = [ + { + name: "blackBox", + real: "20", + imaginary: "20", + tolerance: 0, + }, + { + name: "transformer", + l1: 2, + unit_l1: "nH", + l2: 3, + unit_l2: "nH", + k: 4, + }, + ]; + const settings = { + zo: 50, + frequency: 2440, + frequencyUnit: "MHz", + fSpan: 0, + fSpanUnit: "MHz", + fRes: 10, + zMarkers: [], + vswrCircles: [], + qCircles: [], + nfCircles: [], + gainInCircles: [], + gainOutCircles: [], + }; + const [processedImpedanceResults, _spanResults, _multiZResults, _gainArray, _noiseArray, _numericalFrequency, _RefIn] = allImpedanceCalculations( + circuit, + settings, + ); + + expect(processedImpedanceResults).toEqual({ + zStr: "152.12 - 339.33j", + zPolarStr: "371.87 ∠ -65.85°", + refStr: "0.870 - 0.218j", + refPolarStr: "0.897 ∠ -14.0°", + vswr: "18.5", + qFactor: "2.23", + refReal: 0.8704366392639906, + refImag: -0.2175237548329506, + admString: "0.00110 + 0.00245j", + }); +}); + test("Impedance s1p", () => { const circuit = [ { diff --git a/tests/url.test.js b/tests/url.test.js index 90f7452..5624b6a 100644 --- a/tests/url.test.js +++ b/tests/url.test.js @@ -159,6 +159,7 @@ test("URL clicked them all", () => { l2: 3, unit_l2: "nH", k: 2, + model: "coupledInductor", }, ]); });