@vessel-dsp/compiler 0.0.0-stage → 0.2.0

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.
Files changed (226) hide show
  1. package/README.md +314 -2
  2. package/dist/bake.d.ts +38 -0
  3. package/dist/bake.d.ts.map +1 -0
  4. package/dist/bake.js +101 -0
  5. package/dist/bake.js.map +1 -0
  6. package/dist/bbd-clock.d.ts +171 -0
  7. package/dist/bbd-clock.d.ts.map +1 -0
  8. package/dist/bbd-clock.js +1750 -0
  9. package/dist/bbd-clock.js.map +1 -0
  10. package/dist/block-row.d.ts +51 -0
  11. package/dist/block-row.d.ts.map +1 -0
  12. package/dist/block-row.js +17 -0
  13. package/dist/block-row.js.map +1 -0
  14. package/dist/bypass.d.ts +3 -0
  15. package/dist/bypass.d.ts.map +1 -0
  16. package/dist/bypass.js +228 -0
  17. package/dist/bypass.js.map +1 -0
  18. package/dist/compile.d.ts +24 -0
  19. package/dist/compile.d.ts.map +1 -0
  20. package/dist/compile.js +344 -0
  21. package/dist/compile.js.map +1 -0
  22. package/dist/converter-scale.d.ts +14 -0
  23. package/dist/converter-scale.d.ts.map +1 -0
  24. package/dist/converter-scale.js +133 -0
  25. package/dist/converter-scale.js.map +1 -0
  26. package/dist/couple.d.ts +28 -0
  27. package/dist/couple.d.ts.map +1 -0
  28. package/dist/couple.js +567 -0
  29. package/dist/couple.js.map +1 -0
  30. package/dist/dangling-active-terminal.d.ts +47 -0
  31. package/dist/dangling-active-terminal.d.ts.map +1 -0
  32. package/dist/dangling-active-terminal.js +542 -0
  33. package/dist/dangling-active-terminal.js.map +1 -0
  34. package/dist/declared-program.d.ts +23 -0
  35. package/dist/declared-program.d.ts.map +1 -0
  36. package/dist/declared-program.js +387 -0
  37. package/dist/declared-program.js.map +1 -0
  38. package/dist/denomination.d.ts +48 -0
  39. package/dist/denomination.d.ts.map +1 -0
  40. package/dist/denomination.js +27 -0
  41. package/dist/denomination.js.map +1 -0
  42. package/dist/device-laws.d.ts +237 -0
  43. package/dist/device-laws.d.ts.map +1 -0
  44. package/dist/device-laws.js +3497 -0
  45. package/dist/device-laws.js.map +1 -0
  46. package/dist/diagnostics.d.ts +13 -0
  47. package/dist/diagnostics.d.ts.map +1 -0
  48. package/dist/diagnostics.js +19 -0
  49. package/dist/diagnostics.js.map +1 -0
  50. package/dist/emit.d.ts +8 -0
  51. package/dist/emit.d.ts.map +1 -0
  52. package/dist/emit.js +43 -0
  53. package/dist/emit.js.map +1 -0
  54. package/dist/errors.d.ts +22 -0
  55. package/dist/errors.d.ts.map +1 -0
  56. package/dist/errors.js +39 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/firmware-class.d.ts +69 -0
  59. package/dist/firmware-class.d.ts.map +1 -0
  60. package/dist/firmware-class.js +20 -0
  61. package/dist/firmware-class.js.map +1 -0
  62. package/dist/fixtures/circuits.d.ts +1721 -0
  63. package/dist/fixtures/circuits.d.ts.map +1 -0
  64. package/dist/fixtures/circuits.js +13404 -0
  65. package/dist/fixtures/circuits.js.map +1 -0
  66. package/dist/fixtures/expected.d.ts +257 -0
  67. package/dist/fixtures/expected.d.ts.map +1 -0
  68. package/dist/fixtures/expected.js +311 -0
  69. package/dist/fixtures/expected.js.map +1 -0
  70. package/dist/fixtures/index.d.ts +4 -0
  71. package/dist/fixtures/index.d.ts.map +1 -0
  72. package/dist/fixtures/index.js +8 -0
  73. package/dist/fixtures/index.js.map +1 -0
  74. package/dist/fixtures/registry.d.ts +52 -0
  75. package/dist/fixtures/registry.d.ts.map +1 -0
  76. package/dist/fixtures/registry.js +341 -0
  77. package/dist/fixtures/registry.js.map +1 -0
  78. package/dist/generic-tube-fit.d.ts +12 -0
  79. package/dist/generic-tube-fit.d.ts.map +1 -0
  80. package/dist/generic-tube-fit.js +45 -0
  81. package/dist/generic-tube-fit.js.map +1 -0
  82. package/dist/grounded-clock-supply.d.ts +13 -0
  83. package/dist/grounded-clock-supply.d.ts.map +1 -0
  84. package/dist/grounded-clock-supply.js +45 -0
  85. package/dist/grounded-clock-supply.js.map +1 -0
  86. package/dist/identify.d.ts +50 -0
  87. package/dist/identify.d.ts.map +1 -0
  88. package/dist/identify.js +319 -0
  89. package/dist/identify.js.map +1 -0
  90. package/dist/index.d.ts +10 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +19 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/inert-controls.d.ts +15 -0
  95. package/dist/inert-controls.d.ts.map +1 -0
  96. package/dist/inert-controls.js +266 -0
  97. package/dist/inert-controls.js.map +1 -0
  98. package/dist/latch-seed.d.ts +53 -0
  99. package/dist/latch-seed.d.ts.map +1 -0
  100. package/dist/latch-seed.js +257 -0
  101. package/dist/latch-seed.js.map +1 -0
  102. package/dist/link.d.ts +7 -0
  103. package/dist/link.d.ts.map +1 -0
  104. package/dist/link.js +270 -0
  105. package/dist/link.js.map +1 -0
  106. package/dist/lower.d.ts +79 -0
  107. package/dist/lower.d.ts.map +1 -0
  108. package/dist/lower.js +1855 -0
  109. package/dist/lower.js.map +1 -0
  110. package/dist/netlist.d.ts +79 -0
  111. package/dist/netlist.d.ts.map +1 -0
  112. package/dist/netlist.js +4746 -0
  113. package/dist/netlist.js.map +1 -0
  114. package/dist/non-executable-clock-drivers.d.ts +8 -0
  115. package/dist/non-executable-clock-drivers.d.ts.map +1 -0
  116. package/dist/non-executable-clock-drivers.js +33 -0
  117. package/dist/non-executable-clock-drivers.js.map +1 -0
  118. package/dist/open-category.d.ts +98 -0
  119. package/dist/open-category.d.ts.map +1 -0
  120. package/dist/open-category.js +111 -0
  121. package/dist/open-category.js.map +1 -0
  122. package/dist/over-driven-node.d.ts +33 -0
  123. package/dist/over-driven-node.d.ts.map +1 -0
  124. package/dist/over-driven-node.js +188 -0
  125. package/dist/over-driven-node.js.map +1 -0
  126. package/dist/part-catalog.d.ts +7 -0
  127. package/dist/part-catalog.d.ts.map +1 -0
  128. package/dist/part-catalog.js +6639 -0
  129. package/dist/part-catalog.js.map +1 -0
  130. package/dist/part-number.d.ts +32 -0
  131. package/dist/part-number.d.ts.map +1 -0
  132. package/dist/part-number.js +80 -0
  133. package/dist/part-number.js.map +1 -0
  134. package/dist/partition.d.ts +7 -0
  135. package/dist/partition.d.ts.map +1 -0
  136. package/dist/partition.js +242 -0
  137. package/dist/partition.js.map +1 -0
  138. package/dist/port-full-scale.d.ts +70 -0
  139. package/dist/port-full-scale.d.ts.map +1 -0
  140. package/dist/port-full-scale.js +235 -0
  141. package/dist/port-full-scale.js.map +1 -0
  142. package/dist/pot-orientation.d.ts +114 -0
  143. package/dist/pot-orientation.d.ts.map +1 -0
  144. package/dist/pot-orientation.js +551 -0
  145. package/dist/pot-orientation.js.map +1 -0
  146. package/dist/power-domain-control.d.ts +40 -0
  147. package/dist/power-domain-control.d.ts.map +1 -0
  148. package/dist/power-domain-control.js +142 -0
  149. package/dist/power-domain-control.js.map +1 -0
  150. package/dist/proxy-declaration.d.ts +121 -0
  151. package/dist/proxy-declaration.d.ts.map +1 -0
  152. package/dist/proxy-declaration.js +50 -0
  153. package/dist/proxy-declaration.js.map +1 -0
  154. package/dist/registry.d.ts +323 -0
  155. package/dist/registry.d.ts.map +1 -0
  156. package/dist/registry.js +192 -0
  157. package/dist/registry.js.map +1 -0
  158. package/dist/sparse-schedule.d.ts +65 -0
  159. package/dist/sparse-schedule.d.ts.map +1 -0
  160. package/dist/sparse-schedule.js +421 -0
  161. package/dist/sparse-schedule.js.map +1 -0
  162. package/dist/speaker-load.d.ts +38 -0
  163. package/dist/speaker-load.d.ts.map +1 -0
  164. package/dist/speaker-load.js +97 -0
  165. package/dist/speaker-load.js.map +1 -0
  166. package/dist/stage-coverage.d.ts +21 -0
  167. package/dist/stage-coverage.d.ts.map +1 -0
  168. package/dist/stage-coverage.js +124 -0
  169. package/dist/stage-coverage.js.map +1 -0
  170. package/dist/stamp-partition.d.ts +314 -0
  171. package/dist/stamp-partition.d.ts.map +1 -0
  172. package/dist/stamp-partition.js +472 -0
  173. package/dist/stamp-partition.js.map +1 -0
  174. package/dist/supply-reference.d.ts +19 -0
  175. package/dist/supply-reference.d.ts.map +1 -0
  176. package/dist/supply-reference.js +66 -0
  177. package/dist/supply-reference.js.map +1 -0
  178. package/dist/supply-short.d.ts +32 -0
  179. package/dist/supply-short.d.ts.map +1 -0
  180. package/dist/supply-short.js +118 -0
  181. package/dist/supply-short.js.map +1 -0
  182. package/dist/supply-stamps.d.ts +51 -0
  183. package/dist/supply-stamps.d.ts.map +1 -0
  184. package/dist/supply-stamps.js +363 -0
  185. package/dist/supply-stamps.js.map +1 -0
  186. package/dist/terminal-role.d.ts +109 -0
  187. package/dist/terminal-role.d.ts.map +1 -0
  188. package/dist/terminal-role.js +46 -0
  189. package/dist/terminal-role.js.map +1 -0
  190. package/dist/terminal-roles.d.ts +59 -0
  191. package/dist/terminal-roles.d.ts.map +1 -0
  192. package/dist/terminal-roles.js +92 -0
  193. package/dist/terminal-roles.js.map +1 -0
  194. package/dist/transformer.d.ts +181 -0
  195. package/dist/transformer.d.ts.map +1 -0
  196. package/dist/transformer.js +476 -0
  197. package/dist/transformer.js.map +1 -0
  198. package/dist/types.d.ts +3157 -0
  199. package/dist/types.d.ts.map +1 -0
  200. package/dist/types.js +11 -0
  201. package/dist/types.js.map +1 -0
  202. package/dist/unbounded-operating-point.d.ts +35 -0
  203. package/dist/unbounded-operating-point.d.ts.map +1 -0
  204. package/dist/unbounded-operating-point.js +181 -0
  205. package/dist/unbounded-operating-point.js.map +1 -0
  206. package/dist/unexecuted-region.d.ts +3 -0
  207. package/dist/unexecuted-region.d.ts.map +1 -0
  208. package/dist/unexecuted-region.js +122 -0
  209. package/dist/unexecuted-region.js.map +1 -0
  210. package/dist/unimplemented-control-role.d.ts +3 -0
  211. package/dist/unimplemented-control-role.d.ts.map +1 -0
  212. package/dist/unimplemented-control-role.js +61 -0
  213. package/dist/unimplemented-control-role.js.map +1 -0
  214. package/dist/unreachable-output.d.ts +3 -0
  215. package/dist/unreachable-output.d.ts.map +1 -0
  216. package/dist/unreachable-output.js +97 -0
  217. package/dist/unreachable-output.js.map +1 -0
  218. package/dist/unreadable-terminal-role.d.ts +67 -0
  219. package/dist/unreadable-terminal-role.d.ts.map +1 -0
  220. package/dist/unreadable-terminal-role.js +409 -0
  221. package/dist/unreadable-terminal-role.js.map +1 -0
  222. package/dist/unverified-pinout.d.ts +27 -0
  223. package/dist/unverified-pinout.d.ts.map +1 -0
  224. package/dist/unverified-pinout.js +121 -0
  225. package/dist/unverified-pinout.js.map +1 -0
  226. package/package.json +75 -5
@@ -0,0 +1,476 @@
1
+ // Transformer winding resolution, split out of `lower.ts` (R7, 2026-09-01).
2
+ //
3
+ // This is winding work, not MNA work: the stamps a transformer contributes are two lines in
4
+ // `lowerRegion`, and everything here exists to answer which declared coil drives, which is
5
+ // coupled, and which end is unpaired.
6
+ //
7
+ // Until 2026-09-03 it also had to answer *which terminals form a coil*, from a 110-entry table
8
+ // keyed on folded terminal spellings that grew one packet at a time. `@vessel-dsp/core@0.6.35`
9
+ // makes the coil grouping a declaration (`windings`) and the corpus declares it, so the table is
10
+ // gone and `transformerWindings` reads. R1 in
11
+ // `thoughts/shared/plans/archive/2026-08-31-v2-complexity-reduction-plan.md` is the plan this closes.
12
+ import { LoweringError } from "./errors.js";
13
+ import { GROUND } from "./types.js";
14
+ /**
15
+ * How many `(device, terminal)` references touch each node across the whole netlist.
16
+ *
17
+ * Existence evidence, not a corpus-wide cost: `transformerWindings` is the only reader, and
18
+ * only when its own terminal grouping turns up a winding with a single, unpaired end. A node
19
+ * this stage never asks about -- ground, or any node two ordinary components share -- costs
20
+ * nothing extra to have counted.
21
+ */
22
+ export function nodeOccurrenceCounts(devices) {
23
+ const counts = new Map();
24
+ for (const device of devices) {
25
+ for (const node of device.nodes) {
26
+ counts.set(node, (counts.get(node) ?? 0) + 1);
27
+ }
28
+ }
29
+ return counts;
30
+ }
31
+ /**
32
+ * Nodes where a transformer meets a **selector switch** and nothing else.
33
+ *
34
+ * Connectivity, never a spelling: a node qualifies when the devices touching it are one
35
+ * transformer and one or more plain `switch`es, with no third kind. An output transformer's
36
+ * impedance selector is exactly that shape -- `hiwatt-dr103`'s `SW_IMPEDANCE_SELECTOR` has one
37
+ * `common` and three throws, each throw sharing a node with one secondary tap of
38
+ * `T_OUTPUT_TH7549_2`.
39
+ *
40
+ * **`switch` and not `selector`, deliberately, and this is the whole boundary of this rule.** This
41
+ * repository already models a real 1-of-N selector as its own device kind: `selector` stamps every
42
+ * throw of every pole and lets a control decide which conducts, resolving its position from a
43
+ * declared `Options:` list against `Position:`. That is the right answer for an ohms selector -- it
44
+ * makes the taps *switchable*, so the reflected load changes with the selection, which is the half
45
+ * that matters for power-stage distortion.
46
+ *
47
+ * These two packets do not reach it: they declare `kind: switch` with a `SelectedState: 16 ohms`
48
+ * property rather than the `Options`/`Position` pair the classifier reads. So this rule is the
49
+ * narrow, exact thing that can be said meanwhile -- an unselected throw is open, and an open
50
+ * secondary contributes nothing -- and it **stops applying by construction** the moment a packet
51
+ * declares its selector properly, because a `selector` is not a `switch` and this predicate counts
52
+ * only the latter. It cannot defeat the better model; it is superseded by it.
53
+ */
54
+ export function selectorTapNodes(devices) {
55
+ const kinds = new Map();
56
+ for (const device of devices) {
57
+ for (const node of new Set(device.nodes)) {
58
+ const entry = kinds.get(node) ?? {
59
+ transformers: 0,
60
+ switches: 0,
61
+ others: 0,
62
+ };
63
+ if (device.kind === "transformer") {
64
+ entry.transformers += 1;
65
+ }
66
+ else if (device.kind === "switch") {
67
+ entry.switches += 1;
68
+ }
69
+ else {
70
+ entry.others += 1;
71
+ }
72
+ kinds.set(node, entry);
73
+ }
74
+ }
75
+ const taps = new Set();
76
+ for (const [node, entry] of kinds) {
77
+ if (entry.transformers === 1 && entry.switches >= 1 && entry.others === 0) {
78
+ taps.add(node);
79
+ }
80
+ }
81
+ return taps;
82
+ }
83
+ /**
84
+ * The coils this transformer declares, reduced to the pairs of nodes a stamp needs.
85
+ *
86
+ * **Read, not reconstructed.** Until `@vessel-dsp/core@0.6.35` a transformer's terminals gave no
87
+ * statement of which coil each belonged to, so this stage grouped them with a 110-entry table
88
+ * keyed on folded terminal spellings -- `primaryplus`, `hvreda345vac`, `powertubeheatercenter0v`.
89
+ * That table covered the corpus because it was written from the corpus, one packet at a time, and
90
+ * a transformer nobody had transcribed yet arrived as a refusal naming a winding class instead of
91
+ * the real fault, which was that the document never said what its coils were.
92
+ *
93
+ * Everything the table encoded beyond the grouping stays where it was:
94
+ *
95
+ * - **`end: a|b|tap` is coil order plus each terminal's own role.** The ends are the terminals
96
+ * whose declared role is `winding`; a `windingTap` sits physically where the list puts it.
97
+ * - **`end: unconnected` was never winding structure.** A tap the document wires to nothing is a
98
+ * connectivity fact, read from `terminalOccurrences` below exactly as before.
99
+ * - **`end: selectable` likewise.** Which mains tap is live is a property of the selector switch,
100
+ * and the refusal below still names that switch rather than the transformer.
101
+ */
102
+ export function transformerWindings(device, law, terminalOccurrences, selectorTaps) {
103
+ const declared = device.identity.declaredWindings;
104
+ if (declared === null) {
105
+ throw new LoweringError(`transformer ${device.id} declares no windings, so which of its terminals form each ` +
106
+ "coupled coil is unstated -- a coil grouping is a fact about the transformer that " +
107
+ "this stage reads from the document and will not infer from terminal spellings", device.id);
108
+ }
109
+ const groups = new Map();
110
+ for (const [index, winding] of declared.entries()) {
111
+ const nodes = winding.terminalIndices.flatMap((terminal) => {
112
+ const node = device.nodes[terminal];
113
+ return node === undefined ? [] : [node];
114
+ });
115
+ if (nodes.length === 0) {
116
+ continue;
117
+ }
118
+ const key = windingKey(winding.role, winding.id, groups);
119
+ const centerTap = winding.centerTapAt === null ? undefined : nodes[winding.centerTapAt];
120
+ // Ratings arrive as terminal indices; the reduction and the stamps work in nodes.
121
+ const ratedOhms = new Map();
122
+ for (const rating of winding.impedances) {
123
+ const [from, to] = rating.across;
124
+ const ends = [device.nodes[from], device.nodes[to]].filter((node) => node !== undefined);
125
+ // A rating names the pair it spans, and the reference end of that pair is shared by
126
+ // every rating on the coil. What a stamp needs is the *other* end -- the tap -- so
127
+ // the rating is keyed by whichever node is not the coil's reference.
128
+ const reference = centerTap ?? nodes[0];
129
+ const tap = ends.find((node) => node !== reference) ?? ends[0];
130
+ if (tap !== undefined) {
131
+ ratedOhms.set(tap, rating.ohms);
132
+ }
133
+ }
134
+ groups.set(key, {
135
+ role: winding.role,
136
+ a: nodes[0],
137
+ b: nodes.length > 1 ? nodes[nodes.length - 1] : undefined,
138
+ centerTap,
139
+ // An output tap is an alternative the coil is not simultaneously live at, so the
140
+ // reference tap is not one of them.
141
+ taps: nodes.slice(1, -1).filter((node) => node !== centerTap),
142
+ amplitudeVolts: law.windingAmplitudeVolts[index] ?? null,
143
+ ratedOhms,
144
+ });
145
+ }
146
+ // A coil brought out as several taps needs to be reduced to the pair a stamp can hold, and
147
+ // which pair that is comes from connectivity: the tap something else in the document touches
148
+ // is the live one, and an open tap on an ideal transformer carries no current and reflects
149
+ // nothing, which makes dropping it exact rather than an approximation.
150
+ //
151
+ // The reduction pivots the coil onto the live tap: that tap becomes one end and the coil's
152
+ // other end -- the common -- stays the return. This is what the old table wrote by hand as
153
+ // `secondary16white: end "a"` against `secondarycommonblack: end "b"`, and what its
154
+ // `secondaryalt3`/`secondaryalt2` promotion loop then had to re-derive by preferring 16 over 8
155
+ // over 4 by spelling.
156
+ for (const [name, group] of [...groups]) {
157
+ if (group.taps.length === 0) {
158
+ continue;
159
+ }
160
+ const alternates = [...group.taps, ...(group.b === undefined ? [] : [group.b])];
161
+ const live = alternates.filter((node) => (terminalOccurrences.get(node) ?? 0) > 1);
162
+ const selected = live.filter((node) => !selectorTaps.has(node));
163
+ const chosen = selected.length > 0 ? selected : live;
164
+ if (chosen.length === 0) {
165
+ // Nothing on the coil is wired: it is dangling and the drop below removes it.
166
+ groups.set(name, { ...group, taps: [] });
167
+ continue;
168
+ }
169
+ // **Every live tap is stamped, not just one.** A tapped secondary with two loaded taps is
170
+ // two coupled windings sharing a common, and each takes the turns ratio its own rating
171
+ // gives. Collapsing to one tap silently dropped whatever was on the others -- which is
172
+ // what happened to `orange-rockerverb`'s 8 Ω speaker jack and its feedback resistor.
173
+ //
174
+ // A rating is what makes the extra tap stampable, so a live tap without one refuses.
175
+ // Nothing else in the document says how many turns it sits at.
176
+ const unrated = chosen.filter((node) => !group.ratedOhms.has(node));
177
+ if (chosen.length > 1 && unrated.length > 0) {
178
+ throw new LoweringError(`transformer ${device.id}: winding "${name}" has ${chosen.length} taps carrying a load ` +
179
+ `at once and ${unrated.length} of them state no rated impedance (nodes ` +
180
+ `${unrated.join(", ")}) -- each loaded tap needs its own rating for a turns ` +
181
+ "ratio, and this stage will not guess where on the coil a tap sits", device.id);
182
+ }
183
+ // The coil now spans the common to a live tap, so any reference tap it also declared is
184
+ // outside that span and no longer part of what is stamped. No corpus coil declares both.
185
+ groups.delete(name);
186
+ for (const tap of chosen) {
187
+ groups.set(windingKey(group.role, null, groups), {
188
+ role: group.role,
189
+ a: tap,
190
+ b: group.a,
191
+ centerTap: undefined,
192
+ taps: [],
193
+ amplitudeVolts: group.amplitudeVolts,
194
+ ratedOhms: group.ratedOhms,
195
+ });
196
+ }
197
+ }
198
+ // A winding brought out as several selectable taps needs the selector's own position, and
199
+ // nothing in this document states one. Refused here rather than guessed, and refused *naming
200
+ // the selector* rather than the transformer: the misleading version of this said the primary
201
+ // "has only one terminal declared", which sends a reader to the winding when the missing fact
202
+ // is a switch position.
203
+ //
204
+ // **An unselected throw of a plain make-or-break selector is dropped instead**, and the
205
+ // condition is a second winding to fall back on: a selector connects its common to exactly one
206
+ // throw, so every other tap is open, and an open winding on an ideal transformer carries no
207
+ // current and reflects nothing. `TransformerLaw.turnsRatio` already states that intent --
208
+ // "exact for a transformer with one secondary (tapped or not)". Silent for the same reason the
209
+ // dangling drop below is: lowering has no warning channel, and what is dropped provably cannot
210
+ // change the solved circuit.
211
+ for (const [name, group] of [...groups]) {
212
+ if (group.b !== undefined || !selectorTaps.has(group.a)) {
213
+ continue;
214
+ }
215
+ if ([...groups].some(([other, candidate]) => other !== name && candidate.b !== undefined)) {
216
+ groups.delete(name);
217
+ continue;
218
+ }
219
+ throw new LoweringError(`transformer ${device.id}: winding "${name}" reaches the rest of the document only ` +
220
+ `through a selector (node ${group.a}) and the document states no selected throw ` +
221
+ "for it -- which tap is live is a property of that switch, not of a terminal's " +
222
+ "spelling, and this stage will not pick one", device.id);
223
+ }
224
+ // A winding no end of which connects anywhere else in the document is wired to nothing, and
225
+ // is dropped. Checked by connectivity, never by spelling. `fender-5e3-deluxe-tweed`'s power
226
+ // transformer is the case this was written for: its `filament_a`/`filament_b` pair is
227
+ // declared, typed and touched by no other component, so stamping it would put a source across
228
+ // two rows nothing else holds, which only `gmin` then references. Ground is never dangling, so
229
+ // a winding returning to node 0 is always kept.
230
+ for (const [name, group] of [...groups]) {
231
+ const ends = [group.a, group.b, group.centerTap, ...group.taps].filter((node) => node !== undefined);
232
+ if (ends.every((node) => (terminalOccurrences.get(node) ?? 0) <= 1)) {
233
+ groups.delete(name);
234
+ continue;
235
+ }
236
+ if (group.b !== undefined) {
237
+ continue;
238
+ }
239
+ if (group.role === "bias") {
240
+ // A single-ended bias winding returns inside the transformer. Ten corpus power
241
+ // transformers declare exactly this, and core warns about it (`winding-single-ended`)
242
+ // so the shape stays visible rather than becoming a silent convention here.
243
+ groups.set(name, { ...group, b: GROUND });
244
+ continue;
245
+ }
246
+ throw new LoweringError(`transformer ${device.id}: winding "${name}" declares one terminal, and its node ` +
247
+ `${group.a} connects to another component -- this stage has no model for a used ` +
248
+ "single-ended tap, so it refuses rather than guessing what it means", device.id);
249
+ }
250
+ // A grounded end is the coil's return, so it is the one a stamp measures *from*. Coil order
251
+ // states where the turns are, not a polarity -- the two ends of a winding have no inherent
252
+ // plus and minus -- but a winding stamped with its return as the plus end is inverted against
253
+ // everything that shares that return. Last, because the tap reduction above already puts the
254
+ // common in `b`, and doing it first would offer ground itself as a live alternate.
255
+ for (const [name, group] of groups) {
256
+ if (group.b !== undefined && group.a === GROUND && group.b !== GROUND) {
257
+ groups.set(name, { ...group, a: group.b, b: group.a });
258
+ }
259
+ }
260
+ // A transformer is on the driven path when at least one coil states its own voltage. Tested
261
+ // with `some`, not with the list's length: the list carries one slot per declared coil and a
262
+ // slot is `null` when the source states nothing, so every transformer with any windings has a
263
+ // non-zero length.
264
+ const windings = law.windingAmplitudeVolts.some((volts) => volts !== null)
265
+ ? drivenWindings(device, law, groups)
266
+ : coupledWindings(device, law.turnsRatio, groups);
267
+ if (windings.length === 0) {
268
+ throw new LoweringError(`transformer ${device.id} has a primary and no secondary winding`, device.id);
269
+ }
270
+ return windings;
271
+ }
272
+ /**
273
+ * The impedance this coil is rated at across the pair a stamp uses, or 0 when it states none.
274
+ *
275
+ * Both ends are tried because which one carries the rating depends on the coil: a primary is
276
+ * rated plate-to-plate and a reduced secondary is rated at the live tap that became its `a`.
277
+ */
278
+ function ratedOhmsOf(group) {
279
+ const ohms = group.ratedOhms.get(group.a) ??
280
+ (group.b === undefined ? undefined : group.ratedOhms.get(group.b));
281
+ return ohms !== undefined && ohms > 0 ? ohms : 0;
282
+ }
283
+ /** The key of the coil whose role is `primary`, for the reference-swap comparison below. */
284
+ function primaryName(groups) {
285
+ for (const [name, group] of groups) {
286
+ if (group.role === "primary" || group.role === "drive") {
287
+ return name;
288
+ }
289
+ }
290
+ return "primary";
291
+ }
292
+ /**
293
+ * A key for a coil, unique within its transformer.
294
+ *
295
+ * A role may repeat: `orange-rockerverb`'s power transformer carries two filament windings, a
296
+ * 3.15-0-3.15 V pair for the power tubes and a 6.3 V pair for the preamp. The declared `id`
297
+ * distinguishes them where the document gives one; otherwise the role is suffixed, which is all
298
+ * `secondaryalt2` ever was.
299
+ */
300
+ function windingKey(role, id, groups) {
301
+ const base = id ?? role;
302
+ if (!groups.has(base)) {
303
+ return base;
304
+ }
305
+ for (let suffix = 2;; suffix += 1) {
306
+ const candidate = `${base}#${suffix}`;
307
+ if (!groups.has(candidate)) {
308
+ return candidate;
309
+ }
310
+ }
311
+ }
312
+ /**
313
+ * Each winding driven at its own stated EMF, with no primary modelled.
314
+ *
315
+ * The `primary` group is skipped rather than required: on this path it is the mains side, it
316
+ * carries no audio, and the whole point is that the document need not say anything about it.
317
+ */
318
+ function drivenWindings(device, law, groups) {
319
+ const frequencyHz = law.mainsFrequencyHz;
320
+ if (frequencyHz === null) {
321
+ throw new LoweringError(`transformer ${device.id} is specified by its winding voltages, but this document ` +
322
+ "states no single AC supply frequency for those windings to run at -- a voltage " +
323
+ "with no frequency is not a waveform, and this stage will not pick one", device.id);
324
+ }
325
+ const windings = [];
326
+ for (const [name, group] of groups) {
327
+ if (group.role === "primary" || group.role === "drive") {
328
+ continue;
329
+ }
330
+ const { a, b } = group;
331
+ if (b === undefined) {
332
+ throw new LoweringError(`transformer ${device.id}: winding "${name}" has no pair of ends`, device.id);
333
+ }
334
+ const tap = group.centerTap;
335
+ const amplitudeVolts = group.amplitudeVolts;
336
+ if (amplitudeVolts === null) {
337
+ // **A coil whose source states no voltage is not driven.** This replaced a five-name
338
+ // `HEATER_CLASS_WINDINGS` set that excused the same thing by class, which could not
339
+ // see the reason: `fender-bassman`'s rectifier heater is the only corpus coil in this
340
+ // position, and its packet's own `Derivation` says the 5 V is "assumed from GZ34
341
+ // heater, unprinted on selected schematic" and that typing it would be the
342
+ // invented-typical-value inference the source discipline forbids. So the absence is
343
+ // the packet's decision, not an omission, and the class of the coil is irrelevant to
344
+ // it.
345
+ //
346
+ // The risk this accepts is a *wired* coil left undriven. That is loud rather than
347
+ // silent for anything carrying audio -- an undriven HV winding is a dead B+ rail and
348
+ // a silent amp -- and `requireWindingSpecification` in `netlist.ts` refuses a
349
+ // transformer where no coil states a voltage at all.
350
+ continue;
351
+ }
352
+ // A centre tap is two sources of the stated size about the tap, so the two ends swing in
353
+ // antiphase and the rectifier downstream is full-wave. Never one source of twice the size.
354
+ const halves = tap === undefined
355
+ ? [{ plus: a, minus: b }]
356
+ : [
357
+ { plus: a, minus: tap },
358
+ { plus: tap, minus: b },
359
+ ];
360
+ for (const half of halves) {
361
+ windings.push({
362
+ kind: "driven",
363
+ plus: half.plus,
364
+ minus: half.minus,
365
+ amplitudeVolts,
366
+ frequencyHz,
367
+ sourceOhms: law.windingSourceOhms,
368
+ });
369
+ }
370
+ }
371
+ return windings;
372
+ }
373
+ /** Each secondary coupled to the shared primary through the declared turns ratio. */
374
+ function coupledWindings(device, declaredRatio, groups) {
375
+ // `drive` is a primary in every sense this reduction cares about: it is the coil the signal
376
+ // enters, and the others are referred to it. It is a separate role because a spring tank's
377
+ // coils do not transform each other's voltage -- but a tank shell whose part number is not a
378
+ // tank's lowers here as an ordinary transformer, and then the drive coil is the primary.
379
+ const primary = [...groups.values()].find((group) => group.role === "primary" || group.role === "drive");
380
+ if (primary === undefined || primary.b === undefined) {
381
+ throw new LoweringError(`transformer ${device.id} has no complete primary winding`, device.id);
382
+ }
383
+ // A tapped primary has no single reference winding of its own -- see the docstring's
384
+ // derivation -- so the shared-primary reduction pivots on any OTHER complete, untapped
385
+ // winding instead, which sees the same core flux and can stand in for it.
386
+ let referenceName = primaryName(groups);
387
+ let referenceGroup = primary;
388
+ let reference = { a: primary.a, b: primary.b };
389
+ if (primary.centerTap !== undefined) {
390
+ const candidates = [...groups.entries()].filter((entry) => {
391
+ const [, group] = entry;
392
+ return (group.role !== "primary" &&
393
+ group.role !== "drive" &&
394
+ group.b !== undefined &&
395
+ group.centerTap === undefined);
396
+ });
397
+ if (candidates.length === 0) {
398
+ throw new LoweringError(`transformer ${device.id} has a tapped primary and no untapped winding to use as a ` +
399
+ "reference instead, which this stage cannot reduce to coupled pairs", device.id);
400
+ }
401
+ // Several candidates are the loaded taps of one physical secondary, which the reduction
402
+ // above split into a group each. Any of them can serve -- they all see the same core, and
403
+ // every ratio here is taken against whichever one this picks -- so the highest-rated is
404
+ // chosen: it is the coil's far end and therefore the most complete statement of it.
405
+ const [name, group] = candidates.reduce((best, entry) => ratedOhmsOf(entry[1]) > ratedOhmsOf(best[1]) ? entry : best);
406
+ referenceName = name;
407
+ referenceGroup = group;
408
+ reference = { a: group.a, b: group.b };
409
+ }
410
+ // The rating of the reference coil, against which every other coil's ratio is taken.
411
+ const referenceOhms = ratedOhmsOf(referenceGroup) || null;
412
+ const windings = [];
413
+ for (const [name, group] of groups) {
414
+ if (name === referenceName) {
415
+ continue;
416
+ }
417
+ const { a, b } = group;
418
+ if (b === undefined) {
419
+ throw new LoweringError(`transformer ${device.id}: winding "${name}" has no pair of ends`, device.id);
420
+ }
421
+ const tap = group.centerTap;
422
+ // The tapped primary, reflected through a swapped reference, uses the inverse of the
423
+ // declared ratio, halved -- worked out in the docstring above.
424
+ const isSwappedPrimary = group.role === "primary" || group.role === "drive";
425
+ // **A coil's ratio comes from its own rating**, which is what lets two loaded taps of one
426
+ // secondary be stamped at different ratios. `declaredRatio` is already
427
+ // `sqrt(Zreference / Zcoil)` for a transformer whose ratings this derives from, so for the
428
+ // single-rating coils that is the same arithmetic on the same numbers; the rated path is
429
+ // what the extra taps need.
430
+ //
431
+ // The swapped primary keeps `declaredRatio`: its formula is `2 / sqrt(Zp/Zs)`, and
432
+ // recomputing that as `2 * sqrt(Zs/Zp)` is the same value by algebra and not always the
433
+ // same double.
434
+ //
435
+ // `turnsRatio` on a coupled stamp is (reference turns)/(coil turns), and turns go as the
436
+ // square root of impedance, so a rating at each end of the pair states it completely.
437
+ const coilOhms = ratedOhmsOf(group) || null;
438
+ const rated = referenceOhms !== null && coilOhms !== null;
439
+ const coilRatio = rated
440
+ ? Math.sqrt(referenceOhms / coilOhms)
441
+ : declaredRatio;
442
+ // The swapped primary keeps the reciprocal *expression* the previous rung used rather
443
+ // than the algebraically equal `2 * sqrt(Zref / Zcoil)`: the two agree to within a double's
444
+ // last bit, and the point of reading ratings is to fix a wrong ratio, not to perturb the
445
+ // ten packets whose ratio was already right.
446
+ const localRatio = isSwappedPrimary
447
+ ? 2 /
448
+ (rated
449
+ ? Math.sqrt(coilOhms / referenceOhms)
450
+ : declaredRatio)
451
+ : coilRatio;
452
+ const halves = tap === undefined
453
+ ? [{ plus: a, minus: b, ratio: localRatio }]
454
+ : isSwappedPrimary
455
+ ? [
456
+ { plus: a, minus: tap, ratio: localRatio },
457
+ { plus: tap, minus: b, ratio: localRatio },
458
+ ]
459
+ : [
460
+ { plus: a, minus: tap, ratio: coilRatio * 2 },
461
+ { plus: tap, minus: b, ratio: coilRatio * 2 },
462
+ ];
463
+ for (const half of halves) {
464
+ windings.push({
465
+ kind: "coupled",
466
+ primaryPlus: reference.a,
467
+ primaryMinus: reference.b,
468
+ plus: half.plus,
469
+ minus: half.minus,
470
+ turnsRatio: half.ratio,
471
+ });
472
+ }
473
+ }
474
+ return windings;
475
+ }
476
+ //# sourceMappingURL=transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer.js","sourceRoot":"","sources":["../src/transformer.ts"],"names":[],"mappings":"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"}