@tscircuit/core 0.0.1503 → 0.0.1505

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 (3) hide show
  1. package/dist/index.d.ts +686 -5
  2. package/dist/index.js +685 -102
  3. package/package.json +11 -9
package/dist/index.js CHANGED
@@ -8,7 +8,13 @@ var __export = (target, all) => {
8
8
  var components_exports = {};
9
9
  __export(components_exports, {
10
10
  Ammeter: () => Ammeter,
11
+ AnalogAcSweepSimulation: () => AnalogAcSweepSimulation,
12
+ AnalogAnalysisSimulation: () => AnalogAnalysisSimulation,
13
+ AnalogDcOperatingPointSimulation: () => AnalogDcOperatingPointSimulation,
14
+ AnalogDcSweepSimulation: () => AnalogDcSweepSimulation,
11
15
  AnalogSimulation: () => AnalogSimulation,
16
+ AnalogSweepParameter: () => AnalogSweepParameter,
17
+ AnalogTransientSimulation: () => AnalogTransientSimulation,
12
18
  AutoroutingPhase: () => AutoroutingPhase,
13
19
  Battery: () => Battery,
14
20
  Board: () => Board,
@@ -22666,7 +22672,6 @@ var Group_doInitialSchematicTraceRender = (group) => {
22666
22672
  };
22667
22673
 
22668
22674
  // lib/components/primitive-components/Group/Group_doInitialSimulationSpiceEngineRender.ts
22669
- import { circuitJsonToSpice } from "circuit-json-to-spice";
22670
22675
  import Debug13 from "debug";
22671
22676
 
22672
22677
  // lib/utils/simulation/get-transient-voltage-graph-names-from-spice-netlist.ts
@@ -22739,6 +22744,176 @@ var getSpiceyEngine = () => {
22739
22744
  };
22740
22745
  };
22741
22746
 
22747
+ // lib/components/primitive-components/Group/isCurrentGraph.ts
22748
+ var isCurrentGraph = (element) => element.type === "simulation_transient_current_graph";
22749
+
22750
+ // lib/components/primitive-components/Group/isSimulationCurrentResult.ts
22751
+ var isSimulationCurrentResult = (circuitElement) => circuitElement.type === "simulation_dc_operating_point_current" || circuitElement.type === "simulation_dc_sweep_current_graph" || circuitElement.type === "simulation_ac_sweep_current_graph";
22752
+
22753
+ // lib/components/primitive-components/Group/isSimulationVoltageResult.ts
22754
+ var isSimulationVoltageResult = (circuitElement) => circuitElement.type === "simulation_dc_operating_point_voltage" || circuitElement.type === "simulation_dc_sweep_voltage_graph" || circuitElement.type === "simulation_ac_sweep_voltage_graph";
22755
+
22756
+ // lib/components/primitive-components/Group/isVoltageGraph.ts
22757
+ var isVoltageGraph = (element) => element.type === "simulation_transient_voltage_graph";
22758
+
22759
+ // lib/components/primitive-components/Group/isSimulationAnalysisResult.ts
22760
+ var isSimulationAnalysisResult = (circuitElement) => isVoltageGraph(circuitElement) || isCurrentGraph(circuitElement) || isSimulationVoltageResult(circuitElement) || isSimulationCurrentResult(circuitElement);
22761
+
22762
+ // lib/components/primitive-components/Group/attachSweepCoordinateToSimulationResult.ts
22763
+ var attachSweepCoordinateToSimulationResult = ({
22764
+ simulationResult,
22765
+ simulationParameterSweepCoordinate
22766
+ }) => {
22767
+ if (!simulationParameterSweepCoordinate || !isSimulationAnalysisResult(simulationResult)) {
22768
+ return simulationResult;
22769
+ }
22770
+ const simulationResultWithSweepCoordinate = { ...simulationResult };
22771
+ const simulationResultIdKey = `${simulationResultWithSweepCoordinate.type}_id`;
22772
+ Reflect.deleteProperty(
22773
+ simulationResultWithSweepCoordinate,
22774
+ simulationResultIdKey
22775
+ );
22776
+ simulationResultWithSweepCoordinate.simulation_parameter_sweep_coordinate = simulationParameterSweepCoordinate;
22777
+ return simulationResultWithSweepCoordinate;
22778
+ };
22779
+
22780
+ // lib/components/primitive-components/Group/createSimulationRuns.ts
22781
+ import { circuitJsonToSpice } from "circuit-json-to-spice";
22782
+
22783
+ // lib/components/primitive-components/Group/applyParameterSweepCoordinate.ts
22784
+ var getSourceComponentOrThrow = ({
22785
+ circuitJson,
22786
+ sourceComponentId,
22787
+ isMatchingSourceComponent
22788
+ }) => {
22789
+ const sourceComponent = circuitJson.find(
22790
+ (circuitElement) => isMatchingSourceComponent(circuitElement) && circuitElement.source_component_id === sourceComponentId
22791
+ );
22792
+ if (!sourceComponent) {
22793
+ throw new Error(`Parameter sweep target ${sourceComponentId} was not found`);
22794
+ }
22795
+ return sourceComponent;
22796
+ };
22797
+ var applyParameterSweepCoordinate = ({
22798
+ circuitJson,
22799
+ parameterSweep,
22800
+ simulationParameterSweepCoordinate
22801
+ }) => {
22802
+ const sweptCircuitJson = structuredClone(circuitJson);
22803
+ const parameterValue = simulationParameterSweepCoordinate.parameter_value;
22804
+ if (parameterSweep.parameter_type === "resistance") {
22805
+ const resistor = getSourceComponentOrThrow({
22806
+ circuitJson: sweptCircuitJson,
22807
+ sourceComponentId: parameterSweep.resistor_source_component_id,
22808
+ isMatchingSourceComponent: (circuitElement) => circuitElement.type === "source_component" && circuitElement.ftype === "simple_resistor"
22809
+ });
22810
+ resistor.resistance = parameterValue;
22811
+ return sweptCircuitJson;
22812
+ }
22813
+ if (parameterSweep.parameter_type === "capacitance") {
22814
+ const capacitor = getSourceComponentOrThrow({
22815
+ circuitJson: sweptCircuitJson,
22816
+ sourceComponentId: parameterSweep.capacitor_source_component_id,
22817
+ isMatchingSourceComponent: (circuitElement) => circuitElement.type === "source_component" && circuitElement.ftype === "simple_capacitor"
22818
+ });
22819
+ capacitor.capacitance = parameterValue;
22820
+ return sweptCircuitJson;
22821
+ }
22822
+ if (parameterSweep.parameter_type === "inductance") {
22823
+ const inductor = getSourceComponentOrThrow({
22824
+ circuitJson: sweptCircuitJson,
22825
+ sourceComponentId: parameterSweep.inductor_source_component_id,
22826
+ isMatchingSourceComponent: (circuitElement) => circuitElement.type === "source_component" && circuitElement.ftype === "simple_inductor"
22827
+ });
22828
+ inductor.inductance = parameterValue;
22829
+ return sweptCircuitJson;
22830
+ }
22831
+ if (parameterSweep.parameter_type === "voltage") {
22832
+ const groundNet = sweptCircuitJson.find(
22833
+ (circuitElement) => circuitElement.type === "source_net" && circuitElement.name.toUpperCase() === "GND"
22834
+ );
22835
+ if (!groundNet || groundNet.type !== "source_net") {
22836
+ throw new Error("A voltage parameter sweep requires a GND net");
22837
+ }
22838
+ const sweepVoltageSource = {
22839
+ type: "simulation_voltage_source",
22840
+ simulation_voltage_source_id: `simulation_voltage_source_${simulationParameterSweepCoordinate.simulation_parameter_sweep_id}_${simulationParameterSweepCoordinate.sweep_index}`,
22841
+ is_dc_source: true,
22842
+ positive_source_net_id: parameterSweep.source_net_id,
22843
+ negative_source_net_id: groundNet.source_net_id,
22844
+ voltage: parameterValue
22845
+ };
22846
+ sweptCircuitJson.push(sweepVoltageSource);
22847
+ return sweptCircuitJson;
22848
+ }
22849
+ if (parameterSweep.parameter_type === "current") {
22850
+ const currentSourcePortIds = new Set(
22851
+ sweptCircuitJson.filter(
22852
+ (circuitElement) => circuitElement.type === "source_port" && circuitElement.source_component_id === parameterSweep.current_source_component_id
22853
+ ).map((sourcePort) => sourcePort.source_port_id)
22854
+ );
22855
+ const currentSource = sweptCircuitJson.find(
22856
+ (circuitElement) => circuitElement.type === "simulation_current_source" && (circuitElement.is_dc_source ? Boolean(
22857
+ circuitElement.positive_source_port_id && currentSourcePortIds.has(
22858
+ circuitElement.positive_source_port_id
22859
+ )
22860
+ ) : Boolean(
22861
+ circuitElement.terminal1_source_port_id && currentSourcePortIds.has(
22862
+ circuitElement.terminal1_source_port_id
22863
+ )
22864
+ ))
22865
+ );
22866
+ if (!currentSource) {
22867
+ throw new Error(
22868
+ `Current sweep target ${parameterSweep.current_source_component_id} has no simulation source`
22869
+ );
22870
+ }
22871
+ currentSource.current = parameterValue;
22872
+ return sweptCircuitJson;
22873
+ }
22874
+ throw new Error("Parameter sweep target is incomplete");
22875
+ };
22876
+
22877
+ // lib/components/primitive-components/Group/createSimulationRuns.ts
22878
+ var createSimulationRun = ({
22879
+ circuitJson,
22880
+ simulationParameterSweepCoordinate
22881
+ }) => {
22882
+ const spiceNetlist = circuitJsonToSpice(circuitJson);
22883
+ return {
22884
+ spiceNetlist,
22885
+ spiceString: spiceNetlist.toSpiceString(),
22886
+ simulationParameterSweepCoordinate
22887
+ };
22888
+ };
22889
+ var createSimulationRuns = ({
22890
+ circuitJson,
22891
+ simulationExperimentId
22892
+ }) => {
22893
+ const parameterSweep = circuitJson.find(
22894
+ (circuitElement) => circuitElement.type === "simulation_parameter_sweep" && circuitElement.simulation_experiment_id === simulationExperimentId
22895
+ );
22896
+ if (!parameterSweep) {
22897
+ return [createSimulationRun({ circuitJson })];
22898
+ }
22899
+ return parameterSweep.parameter_values.map((parameterValue, sweepIndex) => {
22900
+ const simulationParameterSweepCoordinate = {
22901
+ simulation_parameter_sweep_id: parameterSweep.simulation_parameter_sweep_id,
22902
+ sweep_index: sweepIndex,
22903
+ parameter_value: parameterValue,
22904
+ parameter_unit: parameterSweep.parameter_unit
22905
+ };
22906
+ return createSimulationRun({
22907
+ circuitJson: applyParameterSweepCoordinate({
22908
+ circuitJson,
22909
+ parameterSweep,
22910
+ simulationParameterSweepCoordinate
22911
+ }),
22912
+ simulationParameterSweepCoordinate
22913
+ });
22914
+ });
22915
+ };
22916
+
22742
22917
  // lib/utils/simulation/parseSimulationGraphValue.ts
22743
22918
  var SI_PREFIX_MULTIPLIERS = {
22744
22919
  p: 1e-12,
@@ -22905,12 +23080,6 @@ var insertIndependentAxisScopeTraces = ({
22905
23080
  // lib/components/primitive-components/Group/isCircuitElementInput.ts
22906
23081
  var isCircuitElementInput = (element) => Boolean(element && typeof element === "object" && "type" in element);
22907
23082
 
22908
- // lib/components/primitive-components/Group/isCurrentGraph.ts
22909
- var isCurrentGraph = (element) => element.type === "simulation_transient_current_graph";
22910
-
22911
- // lib/components/primitive-components/Group/isVoltageGraph.ts
22912
- var isVoltageGraph = (element) => element.type === "simulation_transient_voltage_graph";
22913
-
22914
23083
  // lib/components/primitive-components/Group/Group_doInitialSimulationSpiceEngineRender.ts
22915
23084
  var debug11 = Debug13("tscircuit:core:Group_doInitialSimulationSpiceEngineRender");
22916
23085
  var getCircuitJsonForAnalogSimulation = ({
@@ -22920,10 +23089,14 @@ var getCircuitJsonForAnalogSimulation = ({
22920
23089
  ammeters
22921
23090
  }) => {
22922
23091
  const voltageProbeIds = new Set(
22923
- voltageProbes.map((probe) => probe.simulation_voltage_probe_id).filter((id) => Boolean(id))
23092
+ voltageProbes.map((voltageProbe) => voltageProbe.simulation_voltage_probe_id).filter(
23093
+ (simulationVoltageProbeId) => Boolean(simulationVoltageProbeId)
23094
+ )
22924
23095
  );
22925
23096
  const currentProbeIds = new Set(
22926
- ammeters.map((ammeter) => ammeter.simulation_current_probe_id).filter((id) => Boolean(id))
23097
+ ammeters.map((ammeter) => ammeter.simulation_current_probe_id).filter(
23098
+ (simulationCurrentProbeId) => Boolean(simulationCurrentProbeId)
23099
+ )
22927
23100
  );
22928
23101
  return circuitJson.filter((element) => {
22929
23102
  if (element.type === "simulation_experiment") {
@@ -22935,6 +23108,9 @@ var getCircuitJsonForAnalogSimulation = ({
22935
23108
  if (element.type === "simulation_current_probe") {
22936
23109
  return currentProbeIds.has(element.simulation_current_probe_id);
22937
23110
  }
23111
+ if (element.type === "simulation_parameter_sweep") {
23112
+ return element.simulation_experiment_id === simulationExperimentId;
23113
+ }
22938
23114
  if (element.type === "simulation_oscilloscope_trace") {
22939
23115
  if (element.simulation_voltage_probe_id) {
22940
23116
  return voltageProbeIds.has(element.simulation_voltage_probe_id);
@@ -22943,7 +23119,7 @@ var getCircuitJsonForAnalogSimulation = ({
22943
23119
  return currentProbeIds.has(element.simulation_current_probe_id);
22944
23120
  }
22945
23121
  }
22946
- if (element.type === "simulation_transient_voltage_graph" || element.type === "simulation_transient_current_graph" || element.type === "simulation_unknown_experiment_error") {
23122
+ if (element.type === "simulation_transient_voltage_graph" || element.type === "simulation_transient_current_graph" || element.type === "simulation_dc_operating_point_voltage" || element.type === "simulation_dc_operating_point_current" || element.type === "simulation_dc_sweep_voltage_graph" || element.type === "simulation_dc_sweep_current_graph" || element.type === "simulation_ac_sweep_voltage_graph" || element.type === "simulation_ac_sweep_current_graph" || element.type === "simulation_unknown_experiment_error") {
22947
23123
  return false;
22948
23124
  }
22949
23125
  return true;
@@ -22953,15 +23129,23 @@ function Group_doInitialSimulationSpiceEngineRender(group) {
22953
23129
  if (!group.isSubcircuit) return;
22954
23130
  const { root } = group;
22955
23131
  if (!root) return;
22956
- const analogSims = group.selectAll("analogsimulation");
22957
- if (analogSims.length === 0) return;
23132
+ const analogSimulations = [
23133
+ ...group.selectAll("analogsimulation"),
23134
+ ...group.selectAll("analogtransientsimulation"),
23135
+ ...group.selectAll(
23136
+ "analogdcoperatingpointsimulation"
23137
+ ),
23138
+ ...group.selectAll("analogdcsweepsimulation"),
23139
+ ...group.selectAll("analogacsweepsimulation")
23140
+ ];
23141
+ if (analogSimulations.length === 0) return;
22958
23142
  resetSimulationColorState();
22959
23143
  const spiceEngineMap = { ...root.platform?.spiceEngineMap };
22960
23144
  if (!spiceEngineMap.spicey) {
22961
23145
  spiceEngineMap.spicey = getSpiceyEngine();
22962
23146
  }
22963
- for (const analogSim of analogSims) {
22964
- const simulationExperimentId = analogSim.simulation_experiment_id;
23147
+ for (const analogSimulation of analogSimulations) {
23148
+ const simulationExperimentId = analogSimulation.simulation_experiment_id;
22965
23149
  if (!simulationExperimentId) {
22966
23150
  debug11("No simulation experiment id found, skipping simulation");
22967
23151
  continue;
@@ -22973,7 +23157,7 @@ function Group_doInitialSimulationSpiceEngineRender(group) {
22973
23157
  debug11("No simulation experiment found, skipping simulation");
22974
23158
  continue;
22975
23159
  }
22976
- const simulationScope = analogSim.getGroup() ?? group;
23160
+ const simulationScope = analogSimulation.getGroup() ?? group;
22977
23161
  const voltageProbes = simulationScope.selectAll("voltageprobe");
22978
23162
  const ammeters = simulationScope.selectAll("ammeter");
22979
23163
  const circuitJson = getCircuitJsonForAnalogSimulation({
@@ -22982,13 +23166,16 @@ function Group_doInitialSimulationSpiceEngineRender(group) {
22982
23166
  voltageProbes,
22983
23167
  ammeters
22984
23168
  });
22985
- let spiceString;
22986
- let spiceNetlist;
23169
+ let simulationRuns;
22987
23170
  try {
22988
- spiceNetlist = circuitJsonToSpice(circuitJson);
22989
- spiceString = spiceNetlist.toSpiceString();
22990
- debug11(`Generated SPICE string:
22991
- ${spiceString}`);
23171
+ simulationRuns = createSimulationRuns({
23172
+ circuitJson,
23173
+ simulationExperimentId
23174
+ });
23175
+ debug11(
23176
+ `Generated ${simulationRuns.length} SPICE run(s):
23177
+ ${simulationRuns.map((simulationRun) => simulationRun.spiceString).join("\n")}`
23178
+ );
22992
23179
  } catch (error) {
22993
23180
  debug11(`Failed to convert circuit JSON to SPICE: ${error}`);
22994
23181
  root.db.simulation_unknown_experiment_error.insert({
@@ -22998,15 +23185,15 @@ ${spiceString}`);
22998
23185
  });
22999
23186
  continue;
23000
23187
  }
23001
- const graphNameToProbe = /* @__PURE__ */ new Map();
23002
- const voltageProbesById = /* @__PURE__ */ new Map();
23188
+ const voltageProbeByGraphName = /* @__PURE__ */ new Map();
23189
+ const voltageProbeById = /* @__PURE__ */ new Map();
23003
23190
  const graphDisplayOverridesByProbeId = /* @__PURE__ */ new Map();
23004
23191
  for (const probe of voltageProbes) {
23005
23192
  if (probe.finalProbeName) {
23006
- graphNameToProbe.set(probe.finalProbeName, probe);
23193
+ voltageProbeByGraphName.set(probe.finalProbeName, probe);
23007
23194
  }
23008
23195
  if (probe.simulation_voltage_probe_id) {
23009
- voltageProbesById.set(probe.simulation_voltage_probe_id, probe);
23196
+ voltageProbeById.set(probe.simulation_voltage_probe_id, probe);
23010
23197
  graphDisplayOverridesByProbeId.set(
23011
23198
  probe.simulation_voltage_probe_id,
23012
23199
  getVoltageProbeGraphDisplayOverrides(probe)
@@ -23022,33 +23209,36 @@ ${spiceString}`);
23022
23209
  }
23023
23210
  }
23024
23211
  const scopedCurrentProbeIds = new Set(
23025
- ammeters.map((ammeter) => ammeter.simulation_current_probe_id).filter((id) => Boolean(id))
23212
+ ammeters.map((ammeter) => ammeter.simulation_current_probe_id).filter(
23213
+ (simulationCurrentProbeId) => Boolean(simulationCurrentProbeId)
23214
+ )
23026
23215
  );
23027
- const currentProbesById = /* @__PURE__ */ new Map();
23028
- const currentProbesByName = /* @__PURE__ */ new Map();
23216
+ const currentProbeById = /* @__PURE__ */ new Map();
23217
+ const currentProbeByName = /* @__PURE__ */ new Map();
23029
23218
  for (const probe of root.db.simulation_current_probe.list().filter(
23030
23219
  (probe2) => scopedCurrentProbeIds.has(probe2.simulation_current_probe_id)
23031
23220
  )) {
23032
- currentProbesById.set(probe.simulation_current_probe_id, probe);
23221
+ currentProbeById.set(probe.simulation_current_probe_id, probe);
23033
23222
  if (probe.name !== void 0) {
23034
- currentProbesByName.set(probe.name, probe);
23223
+ currentProbeByName.set(probe.name, probe);
23035
23224
  }
23036
23225
  }
23037
23226
  const orderedSimulationProbes = root.db.simulation_voltage_probe.list().filter(
23038
- (probe) => voltageProbesById.has(probe.simulation_voltage_probe_id)
23227
+ (probe) => voltageProbeById.has(probe.simulation_voltage_probe_id)
23039
23228
  );
23040
- const graphNamesFromNetlist = getTransientVoltageGraphNamesFromSpiceNetlist(spiceNetlist);
23229
+ const firstSpiceNetlist = simulationRuns[0]?.spiceNetlist;
23230
+ const graphNamesFromNetlist = firstSpiceNetlist ? getTransientVoltageGraphNamesFromSpiceNetlist(firstSpiceNetlist) : [];
23041
23231
  if (graphNamesFromNetlist.length === orderedSimulationProbes.length) {
23042
23232
  for (const [
23043
- index,
23233
+ simulationProbeIndex,
23044
23234
  simulationProbe
23045
23235
  ] of orderedSimulationProbes.entries()) {
23046
- const probe = voltageProbesById.get(
23236
+ const probe = voltageProbeById.get(
23047
23237
  simulationProbe.simulation_voltage_probe_id
23048
23238
  );
23049
- const graphName = graphNamesFromNetlist[index];
23239
+ const graphName = graphNamesFromNetlist[simulationProbeIndex];
23050
23240
  if (probe && graphName) {
23051
- graphNameToProbe.set(graphName, probe);
23241
+ voltageProbeByGraphName.set(graphName, probe);
23052
23242
  }
23053
23243
  }
23054
23244
  } else {
@@ -23056,12 +23246,14 @@ ${spiceString}`);
23056
23246
  `Skipping probe-to-graph order mapping because counts differ: probes=${orderedSimulationProbes.length} graphNames=${graphNamesFromNetlist.length}`
23057
23247
  );
23058
23248
  }
23059
- const engineName = analogSim._parsedProps.spiceEngine ?? "spicey";
23249
+ const engineName = analogSimulation.getSpiceEngineName() ?? "spicey";
23060
23250
  const spiceEngine = spiceEngineMap[engineName];
23061
23251
  if (!spiceEngine) {
23062
23252
  throw new Error(
23063
23253
  `SPICE engine "${engineName}" not found in platform config. Available engines: ${JSON.stringify(
23064
- Object.keys(spiceEngineMap).filter((k) => k !== "spicey")
23254
+ Object.keys(spiceEngineMap).filter(
23255
+ (spiceEngineName) => spiceEngineName !== "spicey"
23256
+ )
23065
23257
  )}`
23066
23258
  );
23067
23259
  }
@@ -23071,51 +23263,90 @@ ${spiceString}`);
23071
23263
  );
23072
23264
  group._queueAsyncEffect(effectId, async () => {
23073
23265
  try {
23074
- debug11(`Running simulation with engine: ${engineName}`);
23075
- const result = await spiceEngine.simulate(spiceString);
23076
- debug11(
23077
- `Simulation completed, received ${result.simulationResultCircuitJson.length} elements`
23078
- );
23079
23266
  const insertedVoltageGraphs = [];
23080
23267
  const insertedCurrentGraphs = [];
23081
- for (const rawElement of result.simulationResultCircuitJson) {
23082
- if (!isCircuitElementInput(rawElement)) {
23083
- debug11("Skipping invalid simulation result element");
23084
- continue;
23085
- }
23086
- const element = rawElement;
23087
- if (isVoltageGraph(element)) {
23088
- element.simulation_experiment_id = simulationExperiment.simulation_experiment_id;
23089
- const probeMatch = element.name ? graphNameToProbe.get(element.name) : void 0;
23090
- if (probeMatch) {
23091
- element.color = probeMatch.color ?? void 0;
23092
- element.source_probe_id = probeMatch.simulation_voltage_probe_id ?? void 0;
23093
- }
23094
- }
23095
- if (isCurrentGraph(element)) {
23096
- element.simulation_experiment_id = simulationExperiment.simulation_experiment_id;
23097
- const probeMatch = (element.source_probe_id ? currentProbesById.get(element.source_probe_id) : void 0) ?? (element.name ? currentProbesByName.get(element.name) : void 0);
23098
- if (probeMatch) {
23099
- element.color = probeMatch.color;
23100
- element.source_probe_id = probeMatch.simulation_current_probe_id;
23268
+ for (const simulationRun of simulationRuns) {
23269
+ debug11(`Running simulation with engine: ${engineName}`);
23270
+ const simulationResult = await spiceEngine.simulate(
23271
+ simulationRun.spiceString
23272
+ );
23273
+ debug11(
23274
+ `Simulation completed, received ${simulationResult.simulationResultCircuitJson.length} elements`
23275
+ );
23276
+ for (const simulationResultCircuitElement of simulationResult.simulationResultCircuitJson) {
23277
+ if (!isCircuitElementInput(simulationResultCircuitElement)) {
23278
+ debug11("Skipping invalid simulation result element");
23279
+ continue;
23101
23280
  }
23102
- }
23103
- const insertedElement = root.db.insert(element);
23104
- if (isVoltageGraph(insertedElement)) {
23105
- insertedVoltageGraphs.push({
23106
- type: "voltage",
23107
- graph: insertedElement
23108
- });
23109
- }
23110
- if (isCurrentGraph(insertedElement)) {
23111
- insertedCurrentGraphs.push({
23112
- type: "current",
23113
- graph: insertedElement
23281
+ const simulationResultWithSweepCoordinate = attachSweepCoordinateToSimulationResult({
23282
+ simulationResult: simulationResultCircuitElement,
23283
+ simulationParameterSweepCoordinate: simulationRun.simulationParameterSweepCoordinate
23114
23284
  });
23285
+ if (isVoltageGraph(simulationResultWithSweepCoordinate)) {
23286
+ simulationResultWithSweepCoordinate.simulation_experiment_id = simulationExperiment.simulation_experiment_id;
23287
+ const probeMatch = simulationResultWithSweepCoordinate.name ? voltageProbeByGraphName.get(
23288
+ simulationResultWithSweepCoordinate.name
23289
+ ) : void 0;
23290
+ if (probeMatch) {
23291
+ simulationResultWithSweepCoordinate.color = probeMatch.color ?? void 0;
23292
+ simulationResultWithSweepCoordinate.source_probe_id = probeMatch.simulation_voltage_probe_id ?? void 0;
23293
+ }
23294
+ } else if (isSimulationVoltageResult(simulationResultWithSweepCoordinate)) {
23295
+ simulationResultWithSweepCoordinate.simulation_experiment_id = simulationExperiment.simulation_experiment_id;
23296
+ const probeMatch = voltageProbeById.get(
23297
+ simulationResultWithSweepCoordinate.simulation_voltage_probe_id
23298
+ ) ?? (simulationResultWithSweepCoordinate.name ? voltageProbeByGraphName.get(
23299
+ simulationResultWithSweepCoordinate.name
23300
+ ) : void 0);
23301
+ if (probeMatch?.simulation_voltage_probe_id) {
23302
+ simulationResultWithSweepCoordinate.color = probeMatch.color ?? void 0;
23303
+ simulationResultWithSweepCoordinate.simulation_voltage_probe_id = probeMatch.simulation_voltage_probe_id;
23304
+ }
23305
+ }
23306
+ if (isCurrentGraph(simulationResultWithSweepCoordinate)) {
23307
+ simulationResultWithSweepCoordinate.simulation_experiment_id = simulationExperiment.simulation_experiment_id;
23308
+ const probeMatch = (simulationResultWithSweepCoordinate.source_probe_id ? currentProbeById.get(
23309
+ simulationResultWithSweepCoordinate.source_probe_id
23310
+ ) : void 0) ?? (simulationResultWithSweepCoordinate.name ? currentProbeByName.get(
23311
+ simulationResultWithSweepCoordinate.name
23312
+ ) : void 0);
23313
+ if (probeMatch) {
23314
+ simulationResultWithSweepCoordinate.color = probeMatch.color;
23315
+ simulationResultWithSweepCoordinate.source_probe_id = probeMatch.simulation_current_probe_id;
23316
+ }
23317
+ } else if (isSimulationCurrentResult(simulationResultWithSweepCoordinate)) {
23318
+ simulationResultWithSweepCoordinate.simulation_experiment_id = simulationExperiment.simulation_experiment_id;
23319
+ const probeMatch = currentProbeById.get(
23320
+ simulationResultWithSweepCoordinate.simulation_current_probe_id
23321
+ ) ?? (simulationResultWithSweepCoordinate.name ? currentProbeByName.get(
23322
+ simulationResultWithSweepCoordinate.name
23323
+ ) : void 0);
23324
+ if (probeMatch) {
23325
+ simulationResultWithSweepCoordinate.color = probeMatch.color;
23326
+ simulationResultWithSweepCoordinate.simulation_current_probe_id = probeMatch.simulation_current_probe_id;
23327
+ }
23328
+ }
23329
+ const insertedSimulationResult = root.db.insert(
23330
+ simulationResultWithSweepCoordinate
23331
+ );
23332
+ if (isVoltageGraph(insertedSimulationResult)) {
23333
+ insertedVoltageGraphs.push({
23334
+ type: "voltage",
23335
+ graph: insertedSimulationResult
23336
+ });
23337
+ }
23338
+ if (isCurrentGraph(insertedSimulationResult)) {
23339
+ insertedCurrentGraphs.push({
23340
+ type: "current",
23341
+ graph: insertedSimulationResult
23342
+ });
23343
+ }
23344
+ debug11(
23345
+ `Inserted ${simulationResultWithSweepCoordinate.type} into database`
23346
+ );
23115
23347
  }
23116
- debug11(`Inserted ${element.type} into database`);
23117
23348
  }
23118
- if (analogSim._parsedProps.graphIndependentAxes) {
23349
+ if (analogSimulation.usesIndependentGraphAxes()) {
23119
23350
  insertIndependentAxisScopeTraces({
23120
23351
  db: root.db,
23121
23352
  graphs: [...insertedVoltageGraphs, ...insertedCurrentGraphs],
@@ -23423,7 +23654,7 @@ function Group_getRoutingPhasePlans(group) {
23423
23654
  var package_default = {
23424
23655
  name: "@tscircuit/core",
23425
23656
  type: "module",
23426
- version: "0.0.1502",
23657
+ version: "0.0.1504",
23427
23658
  types: "dist/index.d.ts",
23428
23659
  main: "dist/index.js",
23429
23660
  module: "dist/index.js",
@@ -23459,11 +23690,11 @@ var package_default = {
23459
23690
  "@tscircuit/breakout-point-solver": "github:tscircuit/breakout-point-solver#bac9629",
23460
23691
  "@tscircuit/capacity-autorouter": "^0.0.710",
23461
23692
  "@tscircuit/checks": "0.0.145",
23462
- "@tscircuit/circuit-json-util": "^0.0.100",
23693
+ "@tscircuit/circuit-json-util": "^0.0.101",
23463
23694
  "@tscircuit/common": "^0.0.20",
23464
23695
  "@tscircuit/copper-pour-solver": "0.0.39",
23465
23696
  "@tscircuit/create-fdm-enclosure": "0.0.3",
23466
- "@tscircuit/footprinter": "^0.0.386",
23697
+ "@tscircuit/footprinter": "^0.0.387",
23467
23698
  "@tscircuit/image-utils": "^0.0.8",
23468
23699
  "@tscircuit/infer-cable-insertion-point": "^0.0.2",
23469
23700
  "@tscircuit/infgrid-ijump-astar": "^0.0.35",
@@ -23473,8 +23704,8 @@ var package_default = {
23473
23704
  "@tscircuit/matchpack": "^0.0.48",
23474
23705
  "@tscircuit/math-utils": "^0.0.36",
23475
23706
  "@tscircuit/miniflex": "^0.0.4",
23476
- "@tscircuit/ngspice-spice-engine": "^0.0.19",
23477
- "@tscircuit/props": "^0.0.591",
23707
+ "@tscircuit/ngspice-spice-engine": "^0.0.20",
23708
+ "@tscircuit/props": "^0.0.592",
23478
23709
  "@tscircuit/schematic-match-adapt": "^0.0.18",
23479
23710
  "@tscircuit/schematic-trace-solver": "^0.0.108",
23480
23711
  "@tscircuit/solver-utils": "^0.0.16",
@@ -23488,12 +23719,12 @@ var package_default = {
23488
23719
  "bun-match-svg": "0.0.12",
23489
23720
  "calculate-elbow": "^0.0.12",
23490
23721
  "chokidar-cli": "^3.0.0",
23491
- "circuit-json": "^0.0.453",
23722
+ "circuit-json": "^0.0.454",
23492
23723
  "circuit-json-to-bpc": "^0.0.13",
23493
23724
  "circuit-json-to-connectivity-map": "^0.0.23",
23494
23725
  "circuit-json-to-gltf": "^0.0.107",
23495
- "circuit-json-to-spice": "^0.0.43",
23496
- "circuit-to-svg": "^0.0.391",
23726
+ "circuit-json-to-spice": "^0.0.45",
23727
+ "circuit-to-svg": "^0.0.393",
23497
23728
  concurrently: "^9.1.2",
23498
23729
  "connectivity-map": "^1.0.0",
23499
23730
  debug: "^4.3.6",
@@ -23510,7 +23741,7 @@ var package_default = {
23510
23741
  react: "^19.1.0",
23511
23742
  "react-dom": "^19.1.0",
23512
23743
  "schematic-symbols": "^0.0.233",
23513
- spicets: "^0.0.2",
23744
+ spicets: "^0.0.4",
23514
23745
  spicey: "^0.0.14",
23515
23746
  "stack-svgs": "^0.0.1",
23516
23747
  "ts-expect": "^1.3.0",
@@ -23531,7 +23762,9 @@ var package_default = {
23531
23762
  "@tscircuit/matchpack": "*",
23532
23763
  "circuit-json": "*",
23533
23764
  "circuit-json-to-connectivity-map": "*",
23765
+ "circuit-json-to-spice": "*",
23534
23766
  "schematic-symbols": "*",
23767
+ spicets: "*",
23535
23768
  typescript: "^5.0.0"
23536
23769
  },
23537
23770
  dependencies: {
@@ -29543,6 +29776,7 @@ var PowerSource = class extends NormalComponent3 {
29543
29776
  import { voltageSourceProps } from "@tscircuit/props";
29544
29777
  import { formatSiUnit as formatSiUnit5 } from "format-si-unit";
29545
29778
  var VoltageSource = class extends NormalComponent3 {
29779
+ simulation_voltage_source_id = null;
29546
29780
  get config() {
29547
29781
  const isSquare = this.props.waveShape === "square";
29548
29782
  return {
@@ -29619,11 +29853,10 @@ var VoltageSource = class extends NormalComponent3 {
29619
29853
  const { _parsedProps: props } = this;
29620
29854
  const terminal1Port = this.portMap.terminal1;
29621
29855
  const terminal2Port = this.portMap.terminal2;
29622
- db.simulation_voltage_source.insert({
29623
- type: "simulation_voltage_source",
29856
+ const simulationVoltageSource = db.simulation_voltage_source.insert({
29624
29857
  is_dc_source: false,
29625
- terminal1_source_port_id: terminal1Port.source_port_id,
29626
- terminal2_source_port_id: terminal2Port.source_port_id,
29858
+ terminal1_source_port_id: terminal1Port.source_port_id ?? void 0,
29859
+ terminal2_source_port_id: terminal2Port.source_port_id ?? void 0,
29627
29860
  voltage: props.voltage,
29628
29861
  frequency: props.frequency,
29629
29862
  peak_to_peak_voltage: props.peakToPeakVoltage,
@@ -29634,8 +29867,11 @@ var VoltageSource = class extends NormalComponent3 {
29634
29867
  rise_time: props.riseTime,
29635
29868
  fall_time: props.fallTime,
29636
29869
  pulse_width: props.pulseWidth,
29637
- period: props.period
29870
+ period: props.period,
29871
+ ac_magnitude: props.acMagnitude,
29872
+ ac_phase: props.acPhase
29638
29873
  });
29874
+ this.simulation_voltage_source_id = simulationVoltageSource.simulation_voltage_source_id;
29639
29875
  }
29640
29876
  terminal1 = this.portMap.terminal1;
29641
29877
  terminal2 = this.portMap.terminal2;
@@ -29645,6 +29881,7 @@ var VoltageSource = class extends NormalComponent3 {
29645
29881
  import { currentSourceProps } from "@tscircuit/props";
29646
29882
  import { formatSiUnit as formatSiUnit6 } from "format-si-unit";
29647
29883
  var CurrentSource = class extends NormalComponent3 {
29884
+ simulation_current_source_id = null;
29648
29885
  get config() {
29649
29886
  const symbolName = "current_source";
29650
29887
  return {
@@ -29717,32 +29954,36 @@ var CurrentSource = class extends NormalComponent3 {
29717
29954
  doInitialSimulationRender() {
29718
29955
  const { db } = this.root;
29719
29956
  const { _parsedProps: props } = this;
29720
- const isAc = props.frequency !== void 0 || props.peakToPeakCurrent !== void 0 || props.waveShape !== void 0;
29957
+ const isAc = props.frequency !== void 0 || props.peakToPeakCurrent !== void 0 || props.waveShape !== void 0 || props.acMagnitude !== void 0 || props.acPhase !== void 0;
29721
29958
  const posPort = this.portMap.pos;
29722
29959
  const negPort = this.portMap.neg;
29723
29960
  if (isAc) {
29724
- db.simulation_current_source.insert({
29725
- type: "simulation_current_source",
29961
+ const simulationCurrentSource = db.simulation_current_source.insert({
29726
29962
  is_dc_source: false,
29727
- terminal1_source_port_id: posPort.source_port_id,
29728
- terminal2_source_port_id: negPort.source_port_id,
29963
+ terminal1_source_port_id: posPort.source_port_id ?? void 0,
29964
+ terminal2_source_port_id: negPort.source_port_id ?? void 0,
29729
29965
  current: props.current,
29730
29966
  // DC offset
29731
29967
  frequency: props.frequency,
29732
29968
  peak_to_peak_current: props.peakToPeakCurrent,
29733
29969
  wave_shape: props.waveShape,
29734
29970
  phase: props.phase,
29735
- duty_cycle: props.dutyCycle
29971
+ duty_cycle: props.dutyCycle,
29972
+ ac_magnitude: props.acMagnitude,
29973
+ ac_phase: props.acPhase
29736
29974
  });
29975
+ this.simulation_current_source_id = simulationCurrentSource.simulation_current_source_id;
29737
29976
  } else {
29738
29977
  if (props.current === void 0) return;
29739
- db.simulation_current_source.insert({
29740
- type: "simulation_current_source",
29978
+ const simulationCurrentSource = db.simulation_current_source.insert({
29741
29979
  is_dc_source: true,
29742
- positive_source_port_id: posPort.source_port_id,
29743
- negative_source_port_id: negPort.source_port_id,
29744
- current: props.current
29980
+ positive_source_port_id: posPort.source_port_id ?? void 0,
29981
+ negative_source_port_id: negPort.source_port_id ?? void 0,
29982
+ current: props.current,
29983
+ ac_magnitude: props.acMagnitude,
29984
+ ac_phase: props.acPhase
29745
29985
  });
29986
+ this.simulation_current_source_id = simulationCurrentSource.simulation_current_source_id;
29746
29987
  }
29747
29988
  }
29748
29989
  pos = this.portMap.pos;
@@ -34109,6 +34350,12 @@ var AnalogSimulation = class extends PrimitiveComponent2 {
34109
34350
  zodProps: analogSimulationProps
34110
34351
  };
34111
34352
  }
34353
+ getSpiceEngineName() {
34354
+ return this._parsedProps.spiceEngine;
34355
+ }
34356
+ usesIndependentGraphAxes() {
34357
+ return this._parsedProps.graphIndependentAxes === true;
34358
+ }
34112
34359
  doInitialSimulationRender() {
34113
34360
  const { db } = this.root;
34114
34361
  const { duration, name, startTime, timePerStep, spiceOptions } = this._parsedProps;
@@ -34126,6 +34373,316 @@ var AnalogSimulation = class extends PrimitiveComponent2 {
34126
34373
  }
34127
34374
  };
34128
34375
 
34376
+ // lib/components/primitive-components/AnalogAnalysisSimulation.ts
34377
+ var AnalogAnalysisSimulation = class extends PrimitiveComponent2 {
34378
+ simulation_experiment_id = null;
34379
+ getSpiceEngineName() {
34380
+ return typeof this.props.spiceEngine === "string" ? this.props.spiceEngine : void 0;
34381
+ }
34382
+ usesIndependentGraphAxes() {
34383
+ return this.props.graphIndependentAxes === true;
34384
+ }
34385
+ getOrCreateSimulationExperiment() {
34386
+ if (this.simulation_experiment_id) {
34387
+ return this.root?.db.simulation_experiment.get(
34388
+ this.simulation_experiment_id
34389
+ ) ?? null;
34390
+ }
34391
+ const sweepParameterCount = this.children.filter(
34392
+ (child) => child.componentName === "AnalogSweepParameter"
34393
+ ).length;
34394
+ if (sweepParameterCount > 1) {
34395
+ this.renderError(
34396
+ "An analog simulation can contain at most one sweep parameter."
34397
+ );
34398
+ return null;
34399
+ }
34400
+ const simulationExperiment = this.insertSimulationExperiment();
34401
+ this.simulation_experiment_id = simulationExperiment?.simulation_experiment_id ?? null;
34402
+ return simulationExperiment;
34403
+ }
34404
+ doInitialSimulationRender() {
34405
+ this.getOrCreateSimulationExperiment();
34406
+ }
34407
+ };
34408
+
34409
+ // lib/components/primitive-components/AnalogTransientSimulation.ts
34410
+ import { analogTransientSimulationProps } from "@tscircuit/props";
34411
+ var AnalogTransientSimulation = class extends AnalogAnalysisSimulation {
34412
+ get config() {
34413
+ return {
34414
+ componentName: "AnalogTransientSimulation",
34415
+ zodProps: analogTransientSimulationProps
34416
+ };
34417
+ }
34418
+ insertSimulationExperiment() {
34419
+ const { db } = this.root;
34420
+ const { duration, name, startTime, timePerStep, spiceOptions } = this._parsedProps;
34421
+ return db.simulation_experiment.insert({
34422
+ name: name ?? "spice_transient_analysis",
34423
+ experiment_type: "spice_transient_analysis",
34424
+ end_time_ms: duration,
34425
+ start_time_ms: startTime,
34426
+ time_per_step: timePerStep,
34427
+ spice_options: spiceOptions
34428
+ });
34429
+ }
34430
+ };
34431
+
34432
+ // lib/components/primitive-components/AnalogDcOperatingPointSimulation.ts
34433
+ import { analogDcOperatingPointSimulationProps } from "@tscircuit/props";
34434
+ var AnalogDcOperatingPointSimulation = class extends AnalogAnalysisSimulation {
34435
+ get config() {
34436
+ return {
34437
+ componentName: "AnalogDcOperatingPointSimulation",
34438
+ zodProps: analogDcOperatingPointSimulationProps
34439
+ };
34440
+ }
34441
+ insertSimulationExperiment() {
34442
+ const { name, spiceOptions } = this._parsedProps;
34443
+ return this.root.db.simulation_experiment.insert({
34444
+ name: name ?? "spice_dc_operating_point",
34445
+ experiment_type: "spice_dc_operating_point",
34446
+ spice_options: spiceOptions
34447
+ });
34448
+ }
34449
+ };
34450
+
34451
+ // lib/components/primitive-components/AnalogDcSweepSimulation.ts
34452
+ import { analogDcSweepSimulationProps } from "@tscircuit/props";
34453
+ var AnalogDcSweepSimulation = class extends AnalogAnalysisSimulation {
34454
+ get config() {
34455
+ return {
34456
+ componentName: "AnalogDcSweepSimulation",
34457
+ zodProps: analogDcSweepSimulationProps
34458
+ };
34459
+ }
34460
+ insertSimulationExperiment() {
34461
+ const {
34462
+ name,
34463
+ spiceOptions,
34464
+ sweepSource,
34465
+ sweepStart,
34466
+ sweepStop,
34467
+ sweepStep
34468
+ } = this._parsedProps;
34469
+ const simulationScope = this.getGroup() ?? this.getSubcircuit();
34470
+ const sweepSourceComponent = simulationScope?.selectOne(sweepSource);
34471
+ let dcSweepSourceFields;
34472
+ if (sweepSourceComponent instanceof VoltageSource) {
34473
+ sweepSourceComponent.runRenderPhase("SimulationRender");
34474
+ const simulationVoltageSourceId = sweepSourceComponent.simulation_voltage_source_id;
34475
+ if (!simulationVoltageSourceId) {
34476
+ this.renderError(
34477
+ `DC sweep source "${sweepSource}" must resolve to one voltage or current source.`
34478
+ );
34479
+ return null;
34480
+ }
34481
+ dcSweepSourceFields = {
34482
+ dc_sweep_voltage_source_id: simulationVoltageSourceId,
34483
+ dc_sweep_unit: "V"
34484
+ };
34485
+ } else if (sweepSourceComponent instanceof CurrentSource) {
34486
+ sweepSourceComponent.runRenderPhase("SimulationRender");
34487
+ const simulationCurrentSourceId = sweepSourceComponent.simulation_current_source_id;
34488
+ if (!simulationCurrentSourceId) {
34489
+ this.renderError(
34490
+ `DC sweep source "${sweepSource}" must resolve to one voltage or current source.`
34491
+ );
34492
+ return null;
34493
+ }
34494
+ dcSweepSourceFields = {
34495
+ dc_sweep_current_source_id: simulationCurrentSourceId,
34496
+ dc_sweep_unit: "A"
34497
+ };
34498
+ } else {
34499
+ this.renderError(
34500
+ `DC sweep source "${sweepSource}" must resolve to one voltage or current source.`
34501
+ );
34502
+ return null;
34503
+ }
34504
+ return this.root.db.simulation_experiment.insert({
34505
+ name: name ?? "spice_dc_sweep",
34506
+ experiment_type: "spice_dc_sweep",
34507
+ spice_options: spiceOptions,
34508
+ ...dcSweepSourceFields,
34509
+ dc_sweep_start: sweepStart,
34510
+ dc_sweep_stop: sweepStop,
34511
+ dc_sweep_step: sweepStep
34512
+ });
34513
+ }
34514
+ };
34515
+
34516
+ // lib/components/primitive-components/AnalogAcSweepSimulation.ts
34517
+ import { analogAcSweepSimulationProps } from "@tscircuit/props";
34518
+ var AnalogAcSweepSimulation = class extends AnalogAnalysisSimulation {
34519
+ get config() {
34520
+ return {
34521
+ componentName: "AnalogAcSweepSimulation",
34522
+ zodProps: analogAcSweepSimulationProps
34523
+ };
34524
+ }
34525
+ insertSimulationExperiment() {
34526
+ const {
34527
+ name,
34528
+ spiceOptions,
34529
+ sweepType,
34530
+ samplesPerInterval,
34531
+ sampleCount,
34532
+ startFrequency,
34533
+ stopFrequency
34534
+ } = this._parsedProps;
34535
+ return this.root.db.simulation_experiment.insert({
34536
+ name: name ?? "spice_ac_analysis",
34537
+ experiment_type: "spice_ac_analysis",
34538
+ spice_options: spiceOptions,
34539
+ ac_sweep_type: sweepType,
34540
+ ac_samples_per_interval: samplesPerInterval,
34541
+ ac_sample_count: sampleCount,
34542
+ ac_start_frequency_hz: startFrequency,
34543
+ ac_stop_frequency_hz: stopFrequency
34544
+ });
34545
+ }
34546
+ };
34547
+
34548
+ // lib/components/primitive-components/AnalogSweepParameter.ts
34549
+ import { analogSweepParameterProps } from "@tscircuit/props";
34550
+
34551
+ // lib/components/primitive-components/AnalogSweepParameter_doInitialSimulationRender.ts
34552
+ var parameterUnits = {
34553
+ resistance: "\u03A9",
34554
+ capacitance: "F",
34555
+ inductance: "H",
34556
+ voltage: "V",
34557
+ current: "A"
34558
+ };
34559
+ var isParameterSweepCoordinateInRange = ({
34560
+ parameterSweepCoordinate,
34561
+ stop,
34562
+ step
34563
+ }) => {
34564
+ const tolerance = Math.abs(step) * 1e-9;
34565
+ return step > 0 ? parameterSweepCoordinate <= stop + tolerance : parameterSweepCoordinate >= stop - tolerance;
34566
+ };
34567
+ var getGeneratedParameterSweepCoordinates = ({
34568
+ start,
34569
+ stop,
34570
+ step
34571
+ }) => {
34572
+ const parameterSweepCoordinates = [];
34573
+ for (let parameterSweepCoordinate = start; isParameterSweepCoordinateInRange({
34574
+ parameterSweepCoordinate,
34575
+ stop,
34576
+ step
34577
+ }); parameterSweepCoordinate = start + parameterSweepCoordinates.length * step) {
34578
+ parameterSweepCoordinates.push(parameterSweepCoordinate);
34579
+ if (parameterSweepCoordinates.length > 1e6) {
34580
+ throw new Error("Parameter sweep exceeds 1,000,000 points");
34581
+ }
34582
+ }
34583
+ return parameterSweepCoordinates;
34584
+ };
34585
+ var getParameterSweepTargetSelector = (props) => {
34586
+ if (props.parameterType === "resistance") return props.resistorRef;
34587
+ if (props.parameterType === "capacitance") return props.capacitorRef;
34588
+ if (props.parameterType === "inductance") return props.inductorRef;
34589
+ if (props.parameterType === "voltage") return props.net;
34590
+ return props.currentSourceRef;
34591
+ };
34592
+ var AnalogSweepParameter_doInitialSimulationRender = (analogSweepParameter) => {
34593
+ if (!(analogSweepParameter.parent instanceof AnalogAnalysisSimulation)) {
34594
+ analogSweepParameter.renderError(
34595
+ "analog.sweepparameter must be nested directly in an analog simulation."
34596
+ );
34597
+ return;
34598
+ }
34599
+ const simulationExperiment = analogSweepParameter.parent.getOrCreateSimulationExperiment();
34600
+ if (!simulationExperiment) return;
34601
+ const props = analogSweepParameter._parsedProps;
34602
+ const parameterSweepCoordinates = props.values ?? getGeneratedParameterSweepCoordinates({
34603
+ start: props.start,
34604
+ stop: props.stop,
34605
+ step: props.step
34606
+ });
34607
+ const simulationScope = analogSweepParameter.parent.getGroup() ?? analogSweepParameter.parent.getSubcircuit();
34608
+ const targetSelector = getParameterSweepTargetSelector(props);
34609
+ const parameterUnit = parameterUnits[props.parameterType];
34610
+ const simulationParameterSweepTable = analogSweepParameter.root.db.simulation_parameter_sweep;
34611
+ const simulationParameterSweepFields = {
34612
+ simulation_experiment_id: simulationExperiment.simulation_experiment_id,
34613
+ name: props.name,
34614
+ parameter_type: props.parameterType,
34615
+ parameter_values: parameterSweepCoordinates,
34616
+ parameter_unit: parameterUnit
34617
+ };
34618
+ let simulationParameterSweepId;
34619
+ if (props.parameterType === "voltage") {
34620
+ const sweepNet = simulationScope?.selectOne(targetSelector, {
34621
+ type: "net"
34622
+ });
34623
+ if (!sweepNet?.source_net_id) {
34624
+ analogSweepParameter.renderError(
34625
+ `Voltage sweep net "${targetSelector}" could not be resolved.`
34626
+ );
34627
+ return;
34628
+ }
34629
+ simulationParameterSweepId = simulationParameterSweepTable.insert({
34630
+ ...simulationParameterSweepFields,
34631
+ parameter_type: "voltage",
34632
+ source_net_id: sweepNet.source_net_id
34633
+ }).simulation_parameter_sweep_id;
34634
+ } else {
34635
+ const sweepTarget = simulationScope?.selectOne(targetSelector);
34636
+ const sourceComponentId = sweepTarget?.source_component_id;
34637
+ if (!sourceComponentId) {
34638
+ analogSweepParameter.renderError(
34639
+ `Parameter sweep target "${targetSelector}" could not be resolved.`
34640
+ );
34641
+ return;
34642
+ }
34643
+ if (props.parameterType === "resistance") {
34644
+ simulationParameterSweepId = simulationParameterSweepTable.insert({
34645
+ ...simulationParameterSweepFields,
34646
+ parameter_type: "resistance",
34647
+ resistor_source_component_id: sourceComponentId
34648
+ }).simulation_parameter_sweep_id;
34649
+ } else if (props.parameterType === "capacitance") {
34650
+ simulationParameterSweepId = simulationParameterSweepTable.insert({
34651
+ ...simulationParameterSweepFields,
34652
+ parameter_type: "capacitance",
34653
+ capacitor_source_component_id: sourceComponentId
34654
+ }).simulation_parameter_sweep_id;
34655
+ } else if (props.parameterType === "inductance") {
34656
+ simulationParameterSweepId = simulationParameterSweepTable.insert({
34657
+ ...simulationParameterSweepFields,
34658
+ parameter_type: "inductance",
34659
+ inductor_source_component_id: sourceComponentId
34660
+ }).simulation_parameter_sweep_id;
34661
+ } else {
34662
+ simulationParameterSweepId = simulationParameterSweepTable.insert({
34663
+ ...simulationParameterSweepFields,
34664
+ parameter_type: "current",
34665
+ current_source_component_id: sourceComponentId
34666
+ }).simulation_parameter_sweep_id;
34667
+ }
34668
+ }
34669
+ analogSweepParameter.simulation_parameter_sweep_id = simulationParameterSweepId;
34670
+ };
34671
+
34672
+ // lib/components/primitive-components/AnalogSweepParameter.ts
34673
+ var AnalogSweepParameter = class extends PrimitiveComponent2 {
34674
+ simulation_parameter_sweep_id = null;
34675
+ get config() {
34676
+ return {
34677
+ componentName: "AnalogSweepParameter",
34678
+ zodProps: analogSweepParameterProps
34679
+ };
34680
+ }
34681
+ doInitialSimulationRender() {
34682
+ AnalogSweepParameter_doInitialSimulationRender(this);
34683
+ }
34684
+ };
34685
+
34129
34686
  // lib/components/primitive-components/VoltageProbe.ts
34130
34687
  import { voltageProbeProps } from "@tscircuit/props";
34131
34688
 
@@ -34508,6 +35065,25 @@ var createNamespacedElement = (hostType) => {
34508
35065
  return Component2;
34509
35066
  };
34510
35067
 
35068
+ // lib/namespaced-elements/analog.ts
35069
+ var analog = {
35070
+ transientsimulation: createNamespacedElement(
35071
+ "analogtransientsimulation"
35072
+ ),
35073
+ dcoperatingpointsimulation: createNamespacedElement(
35074
+ "analogdcoperatingpointsimulation"
35075
+ ),
35076
+ dcsweepsimulation: createNamespacedElement(
35077
+ "analogdcsweepsimulation"
35078
+ ),
35079
+ acsweepsimulation: createNamespacedElement(
35080
+ "analogacsweepsimulation"
35081
+ ),
35082
+ sweepparameter: createNamespacedElement(
35083
+ "analogsweepparameter"
35084
+ )
35085
+ };
35086
+
34511
35087
  // lib/namespaced-elements/enclosure.ts
34512
35088
  var EnclosureFdmBoxElement = createNamespacedElement("enclosure.fdm.box");
34513
35089
  var enclosure = {
@@ -34752,7 +35328,13 @@ extendCatalogue({
34752
35328
  });
34753
35329
  export {
34754
35330
  Ammeter,
35331
+ AnalogAcSweepSimulation,
35332
+ AnalogAnalysisSimulation,
35333
+ AnalogDcOperatingPointSimulation,
35334
+ AnalogDcSweepSimulation,
34755
35335
  AnalogSimulation,
35336
+ AnalogSweepParameter,
35337
+ AnalogTransientSimulation,
34756
35338
  AutoroutingPhase,
34757
35339
  Battery,
34758
35340
  Board,
@@ -34856,6 +35438,7 @@ export {
34856
35438
  Via,
34857
35439
  VoltageProbe,
34858
35440
  VoltageSource,
35441
+ analog,
34859
35442
  applyEditEvents,
34860
35443
  applyEditEventsToManualEditsFile,
34861
35444
  applyPcbEditEventsToManualEditsFile,