Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions src/Circuit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -940,8 +940,6 @@ function Circuit({ userCircuit, setUserCircuit, frequency, setSettings, showIdea
const w = 2 * Math.PI * frequency;
const [modalOpen, setModalOpen] = useState(false);
const [modalSparam, setModalSparam] = useState(false);
const [shortedStubDialogOpen, setShortedStubDialogOpen] = useState(false);
const [hasSeenShortedStubPopup, setHasSeenShortedStubPopup] = useState(false);

const sParamIndex = userCircuit.findIndex((c) => c.name === "sparam");
const s1pIndex = userCircuit.findIndex((c) => c.type === "s1p");
Expand Down Expand Up @@ -1128,9 +1126,6 @@ function Circuit({ userCircuit, setUserCircuit, frequency, setSettings, showIdea
setModalOpen(true);
} else if (k == "sparam") {
setModalSparam(true);
} else if (k === "shortedStub" && !hasSeenShortedStubPopup) {
setHasSeenShortedStubPopup(true);
setShortedStubDialogOpen(true);
}
}}
color="bland"
Expand All @@ -1155,14 +1150,6 @@ function Circuit({ userCircuit, setUserCircuit, frequency, setSettings, showIdea
);
})}
</Grid>
<Dialog open={shortedStubDialogOpen} onClose={() => setShortedStubDialogOpen(false)}>
<Box sx={{ p: 2 }}>
<Typography sx={{ mb: 2 }}>{t("circuit.shortedStubDialog")}</Typography>
<Button variant="contained" onClick={() => setShortedStubDialogOpen(false)}>
{t("common.ok")}
</Button>
</Box>
</Dialog>
<div style={{ display: "flex", width: "100%" }}>
<p>
{t("circuit.hint", {
Expand Down
12 changes: 12 additions & 0 deletions src/ReleaseNotes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import TableRow from "@mui/material/TableRow";

function ReleaseNotes() {
const { t } = useTranslation();
const v23 = t("release.v23", { returnObjects: true });
const v22 = t("release.v22", { returnObjects: true });
const v21 = t("release.v21", { returnObjects: true });
const v20features = t("release.v20features", { returnObjects: true });
Expand Down Expand Up @@ -41,6 +42,17 @@ function ReleaseNotes() {
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>
<Typography>v2.3</Typography>
</TableCell>
<TableCell>
<Typography>September 2026</Typography>
</TableCell>
<TableCell>
<ul>{Array.isArray(v23) && v23.map((item, i) => <li key={i}>{item}</li>)}</ul>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Typography>v2.2</Typography>
Expand Down
18 changes: 14 additions & 4 deletions src/impedanceFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import { sParamFrequencyRange } from "./sparam.js"; // Import the sParamFrequenc

const detailedResolution = 50;

export function calculateTlineZ(resolution, component, line_length, beta, startImaginary, startReal, impedanceResolution, startAdmittance) {
export function calculateTlineZ(resolution, component, line_length, beta, startImaginary, startReal, impedanceResolution, startAdmittance, flipArc) {
var tan_beta, zBottom_inv, zTop;
for (var j = 0; j <= resolution; j++) {
if (component.name == "shortedStub") tan_beta = Math.tan((beta * j * line_length) / resolution + Math.PI / 2);
if (flipArc) tan_beta = Math.tan((beta * j * -line_length) / resolution);
else tan_beta = Math.tan((beta * j * line_length) / resolution);

if (component.name == "transmissionLine") {
Expand Down Expand Up @@ -147,8 +147,18 @@ export function calculateImpedance(userCircuit, frequency, resolution, showIdeal
startAdmittance,
);

line_length = ((lengthLambda % 0.5) * speedOfLight) / frequency;
calculateTlineZ(resolution, component, line_length, beta, startImaginary, startReal, impedanceResolution, startAdmittance);
var segmentLambda = lengthLambda % 0.5;
var flipArc = false;
if (component.name === "shortedStub") {
if (segmentLambda > 0 && segmentLambda < 0.25) {
flipArc = true;
segmentLambda = 0.25 - segmentLambda;
} else if (segmentLambda >= 0.25) {
segmentLambda = segmentLambda - 0.25;
}
}
line_length = (segmentLambda * speedOfLight) / frequency;
calculateTlineZ(resolution, component, line_length, beta, startImaginary, startReal, impedanceResolution, startAdmittance, flipArc);
} else if (component.name == "transformer") {
if (component.model === "ideal") {
// Ideal transformer: Z_out = n² * Z_in (turns ratio n from primary to secondary)
Expand Down
4 changes: 2 additions & 2 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey. This work is licensed under a Creative Commons Attribution 4.0 International License. You may not resell this tool",
"version": "v2.0"
"version": "v2.3"
},
"language": {
"label": "Language"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "Tolerance",
"qFactorEquals": "Q Factor = {{v}}"
},
"shortedStubDialog": "Shorted-stub arc starts at 0-ohms (length = 0), therefore will not be connected to the previous point. This may seem unintuitive but makes more sense once considering frequency-span and tolerance",
"hint": "Click components above to add them to the circuit below. Impedance is looking {{direction}}",
"towardsBlackBox": "towards the BLACK BOX",
"towardsTermination": "from the termination",
Expand All @@ -237,6 +236,7 @@
"version": "Version",
"date": "Date",
"notes": "Notes",
"v23": ["Shorted stub arcs now connect from the current impedance point to the final impedance (opposed to from 0ohms)"],
"v22": [
"Reworked .s1p matching: S-parameter block on the left, matching components to the right, load termination at the end",
"Legacy .s1p share links migrate automatically",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey. Esta obra tiene licencia Creative Commons Atribución 4.0 Internacional. No puede revender esta herramienta",
"version": "v2.0"
"version": "v2.3"
},
"language": {
"label": "Idioma"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "Tolerancia",
"qFactorEquals": "Factor Q = {{v}}"
},
"shortedStubDialog": "El arco del stub en corto comienza en 0 Ω (longitud = 0), por lo que no se conectará al punto anterior. Puede parecer poco intuitivo pero encaja con el rango de frecuencia y la tolerancia",
"hint": "Pulse los componentes de arriba para añadirlos al circuito. La impedancia se ve {{direction}}",
"towardsBlackBox": "hacia la CAJA NEGRA",
"towardsTermination": "hacia la TERMINACIÓN",
Expand All @@ -237,6 +236,7 @@
"version": "Versión",
"date": "Fecha",
"notes": "Notas",
"v23": ["Los arcos del stub en corto conectan desde el punto de impedancia actual hasta la impedancia final (en lugar de desde 0 Ω)"],
"v22": [
"Flujo .s1p mejorado: bloque S a la izquierda, red de adaptación a la derecha, terminación al final",
"Los enlaces .s1p antiguos se migran automáticamente",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey. Cette œuvre est sous licence Creative Commons Attribution 4.0 International. Vous ne pouvez pas revendre cet outil",
"version": "v2.0"
"version": "v2.3"
},
"language": {
"label": "Langue"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "Tolérance",
"qFactorEquals": "Facteur Q = {{v}}"
},
"shortedStubDialog": "L’arc du stub court-circuité part de 0 Ω (longueur = 0) et ne se raccorde donc pas au point précédent. Cela peut surprendre mais est cohérent avec la plage de fréquence et la tolérance",
"hint": "Cliquez sur les composants ci-dessus pour les ajouter au circuit. L’impédance est vue {{direction}}",
"towardsBlackBox": "vers la BOÎTE NOIRE",
"towardsTermination": "vers la TERMINAISON",
Expand All @@ -237,6 +236,7 @@
"version": "Version",
"date": "Date",
"notes": "Notes",
"v23": ["Les arcs du stub court-circuité partent du point d’impédance actuel jusqu’à l’impédance finale (au lieu de partir de 0 Ω)"],
"v22": [
"Adaptation .s1p refaite : bloc S à gauche, réseau d’adaptation à droite, terminaison en fin de chaîne",
"Les liens .s1p existants sont migrés automatiquement",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey। यह कार्य Creative Commons Attribution 4.0 International लाइसेंस के अंतर्गत है। आप इस टूल को पुनः बेच नहीं सकते",
"version": "v2.0"
"version": "v2.3"
},
"language": {
"label": "भाषा"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "टॉलरेंस",
"qFactorEquals": "Q फैक्टर = {{v}}"
},
"shortedStubDialog": "शॉर्टेड-स्टब चाप 0 ओम (लंबाई = 0) से शुरू होता है, इसलिए पिछले बिंदु से जुड़ा नहीं होगा। यह अजीब लग सकता है लेकिन आवृत्ति-स्पैन और टॉलरेंस के साथ अधिक समझ में आता है",
"hint": "ऊपर के घटकों पर क्लिक करके उन्हें नीचे सर्किट में जोड़ें। इम्पीडेंस {{direction}} देख रहा है",
"towardsBlackBox": "ब्लैक बॉक्स की ओर",
"towardsTermination": "टर्मिनेशन की ओर",
Expand All @@ -237,6 +236,7 @@
"version": "संस्करण",
"date": "तारीख",
"notes": "नोट्स",
"v23": ["शॉर्टेड स्टब चाप अब वर्तमान इम्पीडेंस बिंदु से अंतिम इम्पीडेंस तक जुड़ते हैं (0 Ω से नहीं)"],
"v22": [
".s1p मिलान अपडेट: बाएँ S-पैरामीटर, दाएँ मिलान नेटवर्क, अंत में टर्मिनेशन",
"पुराने .s1p लिंक स्वचालित रूप से माइग्रेट होते हैं",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey. 本作品はクリエイティブ・コモンズ表示4.0国際ライセンスの下で提供されています。本ツールの再販は禁止です",
"version": "v2.0"
"version": "v2.3"
},
"language": {
"label": "言語"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "許容差",
"qFactorEquals": "Q = {{v}}"
},
"shortedStubDialog": "短絡スタブの円弧は0Ω(長さ=0)から始まるため、前の点には接続されません。周波数スパンと許容差を考えると納得できます",
"hint": "上の部品をクリックして下の回路に追加します。インピーダンスは{{direction}}を見ています",
"towardsBlackBox": "ブラックボックス方向",
"towardsTermination": "終端方向",
Expand All @@ -237,6 +236,7 @@
"version": "バージョン",
"date": "日付",
"notes": "内容",
"v23": ["短絡スタブの円弧が現在のインピーダンス点から最終インピーダンスまでつながるように改善(0Ωからではなく)"],
"v22": [
".s1pマッチングを改善:左にSパラメータ、右にマッチングネットワーク、末尾に終端",
"旧.s1p共有URLは自動的に移行",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey. Bu çalışma Creative Commons Atıf 4.0 Uluslararası Lisansı altındadır. Bu aracı yeniden satamazsınız",
"version": "sürüm 2.0"
"version": "sürüm 2.3"
},
"language": {
"label": "Dil"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "Tolerans",
"qFactorEquals": "Q faktörü = {{v}}"
},
"shortedStubDialog": "Kısa devre stub yayı 0 Ω’da (uzunluk = 0) başlar, bu yüzden önceki noktaya bağlı görünmez. İlk bakışta karşı sezgine gelebilir; frekans aralığı ve tolerans düşünüldüğünde daha anlaşılır olur",
"hint": "Aşağıdaki devreye eklemek için yukarıdaki bileşenlere tıklayın. Empedans yönü: {{direction}}",
"towardsBlackBox": "KARA KUTU'ya doğru",
"towardsTermination": "SONLANDIRMA'ya doğru",
Expand All @@ -237,6 +236,7 @@
"version": "Sürüm",
"date": "Tarih",
"notes": "Notlar",
"v23": ["Kısa devre stub yayları artık geçerli empedans noktasından son empedansa bağlanır (0 Ω yerine)"],
"v22": [
".s1p eşleme yenilendi: solda S-parametre, sağda eşleme ağı, sonda sonlandırma",
"Eski .s1p paylaşım bağlantıları otomatik taşınır",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"footer": {
"license": "© {{year}} Will Kelsey。本作品采用知识共享署名 4.0 国际许可协议。不得转售本工具",
"version": "v2.0"
"version": "v2.3"
},
"language": {
"label": "语言"
Expand Down Expand Up @@ -212,7 +212,6 @@
"tolerance": "容差",
"qFactorEquals": "Q 值 = {{v}}"
},
"shortedStubDialog": "短路短截线弧从 0 欧(长度 = 0)开始,因此不会连接到前一点。看似不直观,但结合频率范围与容差后更易理解",
"hint": "点击上方元件将其加入下方电路。阻抗为看向 {{direction}}",
"towardsBlackBox": "黑盒方向",
"towardsTermination": "终端方向",
Expand All @@ -237,6 +236,7 @@
"version": "版本",
"date": "日期",
"notes": "说明",
"v23": ["短路短截线弧现从当前阻抗点连接到最终阻抗(而非从 0 Ω 起)"],
"v22": ["改进 .s1p 匹配流程:左侧 S 参数、右侧匹配网络、末端负载", "旧 .s1p 分享链接自动迁移", "反射系数与原始 S 参数数据同时绘制"],
"v21": ["新增 S 参数元件", "新增用于 s2p 增益的增益圆", "新增若干 S 参数教程"],
"v20a": "网站从 will-kelsey.com/smith_chart/ 迁移至 onlinesmithchart.com",
Expand Down
30 changes: 25 additions & 5 deletions tests/impedance.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ import { readFileSync /*, writeFileSync*/ } from "fs";
import { join } from "path";
import { allImpedanceCalculations, calculateImpedance } from "../src/impedanceFunctions.js";

const FLOAT_PRECISION = 10;

function expectProcessedImpedanceResults(actual, expected) {
const { refReal, refImag, ...expectedRest } = expected;
expect(actual).toMatchObject(expectedRest);
expect(actual.refReal).toBeCloseTo(refReal, FLOAT_PRECISION);
expect(actual.refImag).toBeCloseTo(refImag, FLOAT_PRECISION);
}

function expectImpedanceArcs(actual, expected, precision = FLOAT_PRECISION) {
expect(actual.length).toBe(expected.length);
for (let i = 0; i < actual.length; i++) {
expect(actual[i].length).toBe(expected[i].length);
for (let j = 0; j < actual[i].length; j++) {
expect(actual[i][j].real).toBeCloseTo(expected[i][j].real, precision);
expect(actual[i][j].imaginary).toBeCloseTo(expected[i][j].imaginary, precision);
}
}
}

test("Transmission line impedance test", () => {
const circuit = [
{ name: "blackBox", real: 25, imaginary: -25 },
Expand All @@ -20,7 +40,7 @@ test("Transmission line impedance test", () => {
{ real: 46.53103192423643, imaginary: 48.109436254243874 },
],
];
expect(impedance).toEqual(expected);
expectImpedanceArcs(impedance, expected);
});

test("Impedance L-R-Shorted-Stub", () => {
Expand Down Expand Up @@ -67,7 +87,7 @@ test("Impedance L-R-Shorted-Stub", () => {
settings,
);

expect(processedImpedanceResults).toEqual({
expectProcessedImpedanceResults(processedImpedanceResults, {
zStr: "27.88 - 11.2j",
zPolarStr: "30.05 ∠ -21.88°",
refStr: "-0.258 - 0.181j",
Expand Down Expand Up @@ -116,7 +136,7 @@ test("Cap with ESL and ESR", () => {
settings,
);

expect(processedImpedanceResults).toEqual({
expectProcessedImpedanceResults(processedImpedanceResults, {
zStr: "73.00 - 34.57j",
zPolarStr: "80.77 ∠ -25.34°",
refStr: "0.246 - 0.212j",
Expand Down Expand Up @@ -166,7 +186,7 @@ test("Ideal Transformer", () => {
settings,
);

expect(processedImpedanceResults).toEqual({
expectProcessedImpedanceResults(processedImpedanceResults, {
zStr: "83.23 + 83.23j",
zPolarStr: "117.71 ∠ 45.00°",
refStr: "0.460 + 0.337j",
Expand Down Expand Up @@ -215,7 +235,7 @@ test("Coupled Transformer", () => {
settings,
);

expect(processedImpedanceResults).toEqual({
expectProcessedImpedanceResults(processedImpedanceResults, {
zStr: "152.12 - 339.33j",
zPolarStr: "371.87 ∠ -65.85°",
refStr: "0.870 - 0.218j",
Expand Down
Loading