public void When_RCFilterConstantTransientGear_Expect_Reference() { // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", 10.0), new Resistor("R1", "in", "out", 10), new Capacitor("C1", "out", "0", 20)); // Create the transient analysis var tran = new Transient("tran 1", 1.0, 10.0); // TODO: review this test // tran.Configurations.Get<TimeConfiguration>().Method = new Gear(); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(args.GetVoltage("out"), 10.0, 1e-12); }; tran.Run(ckt); // Let's run the simulation twice to check if it is consistent try { tran.Run(ckt); } catch (Exception) { throw new Exception(@"Cannot run transient analysis twice"); } }
public void When_PwlHasTwoPositiveTimePointsTheyShouldBeHit_Expect_Reference() { // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pwl() { Points = new[] { new Point(1.111, 2.0), new Point(3.34, 2.0) } }), new Resistor("R1", "in", "0", 10.0) ); // Create the transient analysis var tran = new Transient("Tran 1", 1.3e-6, 10.0); bool wasHit1 = false; bool wasHit2 = false; tran.ExportSimulationData += (sender, args) => { if (args.Time == 1.111) { wasHit1 = true; } if (args.Time == 3.34) { wasHit2 = true; } Assert.AreEqual(2.0, args.GetVoltage("in"), 1e-12); }; tran.Run(ckt); Assert.True(wasHit1); Assert.True(wasHit2); }
public void When_PwlHasManyLinearPoints_Expect_Reference() { int n = 10000; var pts = new Point[n]; for (var i = 0; i < n; i++) { pts[i] = new Point(i, i); } // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pwl() { Points = pts }), new Resistor("R1", "in", "0", 10.0) ); // Create the transient analysis var tran = new Transient("Tran 1", 1e-2, n - 1); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(args.Time, args.GetVoltage("in"), 1e-12); }; tran.Run(ckt); }
public void When_TransientRerun_Expect_Same() { // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", 10.0), new Resistor("R1", "in", "out", 10), new Capacitor("C1", "out", "0", 20) ); // Create the transient analysis var tran = new Transient("tran 1", 1.0, 10.0); tran.TimeParameters.InitialConditions["out"] = 0; var export = new RealVoltageExport(tran, "out"); // Run the simulation a first time for building the reference values var r = new List <double>(); void BuildReference(object sender, ExportDataEventArgs args) => r.Add(export.Value); tran.ExportSimulationData += BuildReference; tran.Run(ckt); tran.ExportSimulationData -= BuildReference; // Rerun the simulation for building the reference values var index = 0; void CheckReference(object sender, ExportDataEventArgs args) => Assert.AreEqual(r[index++], export.Value, 1e-20); tran.ExportSimulationData += CheckReference; tran.Rerun(); tran.ExportSimulationData -= CheckReference; }
public void When_IntegrateTransient_Expect_Reference() { var ckt = new Circuit( new CurrentSource("Itmp", "a", "0", new Sine(0, 1, 100)), new Capacitor("C1", "a", "0", 1.0), // this will integrate the variable new VoltageSource("Vtmp", "b", "0", new Sine(0, 1, 100)), new BehavioralVoltageSource("V1", "in", "0", "idt(V(b))")); var tran = new Transient("tran", 1e-3, 0.1); tran.TimeParameters.InitialConditions["a"] = 0.0; var expectedExport = new RealVoltageExport(tran, "a"); var actualExport = new RealVoltageExport(tran, "in"); tran.ExportSimulationData += (sender, args) => { if (args.Time > 0) { var expected = expectedExport.Value; var actual = -actualExport.Value; Assert.AreEqual(expected, actual, 1e-9); } }; tran.Run(ckt); }
public void When_LowpassRCTransientTrapezoidal_Expect_Reference() { /* * A test for a lowpass RC circuit (DC voltage, resistor, capacitor) * The initial voltage on capacitor is 0V. The result should be an exponential converging to dcVoltage. */ double dcVoltage = 10; var resistorResistance = 10e3; // 10000; var capacitance = 1e-6; // 0.000001; var tau = resistorResistance * capacitance; // Build circuit var ckt = new Circuit( new BehavioralCapacitor("C1", "OUT", "0", $"{capacitance}*x"), new Resistor("R1", "IN", "OUT", resistorResistance), new VoltageSource("V1", "IN", "0", dcVoltage) ); // Create simulation, exports and references var tran = new Transient("tran", 1e-8, 10e-6); tran.TimeParameters.InitialConditions["OUT"] = 0.0; IExport <double> exports = new RealPropertyExport(tran, "C1", "v"); Func <double, double> reference = t => dcVoltage * (1.0 - Math.Exp(-t / tau)); // Run tran.ExportSimulationData += (sender, args) => { double v_actual = args.GetVoltage("OUT"); double v_reference = reference(args.Time); double tol = Math.Max(Math.Abs(v_actual), Math.Abs(v_reference)) * 1e-3 + 1e-12; Assert.AreEqual(v_reference, v_actual, tol); }; tran.Run(ckt); }
public void When_PulseBreakpoints_Expect_Reference() { var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pulse(0, 1, 0.2, 0.1, 0.1, 0.4, 1.0))); var tran = new Transient("tran", 0.1, 1.2); bool riseHit = false, risenHit = false, fallHit = false, fallenHit = false; tran.ExportSimulationData += (sender, args) => { if (Math.Abs(args.Time - 0.2) < 1e-12) { riseHit = true; } if (Math.Abs(args.Time - 0.3) < 1e-12) { risenHit = true; } if (Math.Abs(args.Time - 0.7) < 1e-12) { fallHit = true; } if (Math.Abs(args.Time - 0.8) < 1e-12) { fallenHit = true; } }; tran.Run(ckt); Assert.True(riseHit); Assert.True(risenHit); Assert.True(fallHit); Assert.True(fallenHit); }
public void When_LazyLoadExport_Expect_Reference() { // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", 10), new Resistor("R1", "in", "0", 1e3)); // Create the transient analysis var tran = new Transient("Tran 1", 1e-6, 10.0); Export <double> export = null; tran.ExportSimulationData += (sender, args) => { // If the time > 5.0 then start exporting our stuff if (args.Time > 5.0) { if (export == null) { export = new RealPropertyExport((Simulation)sender, "R1", "i"); } Assert.AreEqual(10.0 / 1e3, export.Value, 1e-12); } }; tran.Run(ckt); }
public void When_SimpleCapacitorTransient_Expect_Reference() { var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Sine(0, 1, 1e3)), new Capacitor("C1", "in", "0", 1e-3), new BehavioralCapacitor("C2", "in", "0", "1m*x")); var tran = new Transient("tran", 1e-6, 1e-3); // Check currents var refCurrent = new RealPropertyExport(tran, "C1", "i"); var actCurrent = new RealPropertyExport(tran, "C2", "i"); // Check voltages var refVoltage = new RealPropertyExport(tran, "C1", "v"); var actVoltage = new RealPropertyExport(tran, "C2", "v"); // check powers var refPower = new RealPropertyExport(tran, "C1", "p"); var actPower = new RealPropertyExport(tran, "C2", "p"); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(refCurrent.Value, actCurrent.Value, 1e-9); Assert.AreEqual(refVoltage.Value, actVoltage.Value, 1e-9); Assert.AreEqual(refPower.Value, actPower.Value, 1e-9); }; tran.Run(ckt); }
public void When_RCFilterTransient_Expect_NoException() { // <example_Transient> // Build the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pulse(0.0, 5.0, 0.01, 1e-3, 1e-3, 0.02, 0.04)), new Resistor("R1", "in", "out", 10.0e3), new Capacitor("C1", "out", "0", 1e-6) ); // Create the simulation var tran = new Transient("Tran 1", 1e-3, 0.1); // Make the exports var inputExport = new RealVoltageExport(tran, "in"); var outputExport = new RealVoltageExport(tran, "out"); // Simulate tran.ExportSimulationData += (sender, args) => { var input = inputExport.Value; var output = outputExport.Value; }; tran.Run(ckt); // </example_Transient> }
/// <summary> /// Perform a test for transient analysis where the reference is a function in time /// </summary> /// <param name="sim">Simulation</param> /// <param name="ckt">Circuit</param> /// <param name="exports">Exports</param> /// <param name="references">References</param> protected void AnalyzeTransient(Transient sim, Circuit ckt, IEnumerable <Export <double> > exports, IEnumerable <Func <double, double> > references) { sim.ExportSimulationData += (sender, data) => { using (var exportsIt = exports.GetEnumerator()) using (var referencesIt = references.GetEnumerator()) { while (exportsIt.MoveNext() && referencesIt.MoveNext()) { var t = data.Time; var actual = exportsIt.Current?.Value ?? throw new ArgumentNullException(); var expected = referencesIt.Current?.Invoke(t) ?? throw new ArgumentNullException(); var tol = Math.Max(Math.Abs(actual), Math.Abs(expected)) * RelTol + AbsTol; try { Assert.AreEqual(expected, actual, tol); } catch (Exception ex) { var msg = $"{ex.Message} at t={data.Time} s"; throw new Exception(msg, ex); } } } }; sim.Run(ckt); }
public void When_ParallelMultiplierTransient_Expect_Reference() { // Create circuit // WARNING: We simulate both possibilities together, because the // timestep varies if we split them due to different timestep truncation. var ckt = new Circuit( new VoltageSource("V1r", "inr", "0", new Pulse(1, 5, 1e-6, 1e-9, 0.5e-6, 2e-6, 6e-6)), new VoltageSource("Vsupplyr", "vddr", "0", 5), new Resistor("R1r", "outr", "vddr", 1.0e3), CreateMOS1("M1r", "outr", "inr", "0", "0", "MM"), CreateMOS1("M2r", "outr", "inr", "0", "0", "MM"), new VoltageSource("V1a", "ina", "0", new Pulse(1, 5, 1e-6, 1e-9, 0.5e-6, 2e-6, 6e-6)), new VoltageSource("Vsupplya", "vdda", "0", 5), new Resistor("R1a", "outa", "vdda", 1.0e3), CreateMOS1("M1a", "outa", "ina", "0", "0", "MM") .SetParameter("m", 2.0), CreateMOS1Model("MM", "IS=1e-32 VTO=3.03646 LAMBDA=0 KP=5.28747 CGSO=6.5761e-06 CGDO=1e-11") ); // Create simulation var tran = new Transient("tran", 1e-9, 10e-6); tran.BiasingParameters.Gmin = 0.0; // May interfere with comparison var v_ref = new RealVoltageExport(tran, "outr"); var v_act = new RealVoltageExport(tran, "outa"); tran.ExportSimulationData += (sender, args) => { var tol = Math.Max(Math.Abs(v_ref.Value), Math.Abs(v_act.Value)) * CompareRelTol + CompareAbsTol; Assert.AreEqual(v_ref.Value, v_act.Value, tol); }; tran.Run(ckt); }
public void When_ChangeParameterInTransient_Expect_NoException() { // <example_change_parameter_circuit> // Build a circuit var ckt = new Circuit( new Resistor("R1", "in", "out", 1.0e3), new Resistor("R2", "out", "0", 1.0e3), new Capacitor("C1", "out", "0", 0.5e-9), new VoltageSource("V1", "in", "0", new Pulse(0, 5, 1e-6, 1e-6, 1e-6, 1e-5, 2e-5)) ); // </example_change_parameter_circuit> // <example_change_parameter_transient> // Create the transient analysis and exports var tran = new Transient("tran", 1e-6, 10e-5); var outputExport = new RealVoltageExport(tran, "out"); tran.ExportSimulationData += (sender, args) => { var time = args.Time; var output = outputExport.Value; }; // </example_change_parameter_transient> // <example_change_parameter_setup> // Now we need to make sure we have a reference to both the base parameters and temperature behavior // of the resistor SpiceSharp.Components.ResistorBehaviors.BaseParameters bp = null; SpiceSharp.Components.ResistorBehaviors.TemperatureBehavior tb = null; tran.AfterSetup += (sender, args) => { tran.EntityParameters["R2"].TryGet(out bp); tran.EntityBehaviors["R2"].TryGet(out tb); }; // </example_change_parameter_setup> // <example_change_parameter_load> // Before loading the resistor, let's change its value first! tran.BeforeLoad += (sender, args) => { // First we need to figure out the timepoint that will be loaded var time = tran.Method.Time; // Then we need to calculate the resistance for "R2" var resistance = 1.0e3 * (1 + time * 1.0e5); // Now let's update the parameter if (bp == null || tb == null) { return; } bp.Resistance.Value = resistance; tb.Temperature(tran); }; // Run the simulation tran.Run(ckt); // </example_change_parameter_load> }
public void When_CurrentSourceResistorTransient_Expect_NoException() { // Found by Marcin Golebiowski var ckt = new Circuit( new CurrentSource("I1", "1", "0", new Pulse(0, 6, 3.69e-6, 41e-9, 41e-9, 3.256e-6, 6.52e-6)), new Resistor("R1", "1", "0", 10.0) ); var tran = new Transient("tran", 1e-8, 1e-5); tran.Run(ckt); }
public void When_TimeDependent_Expect_Reference() { var ckt = new Circuit( new VoltageSource("Vtmp", "a", "0", 0.0), // Needed to have at least one independent source new BehavioralVoltageSource("V1", "in", "0", "5*sin(time*10*pi)")); var tran = new Transient("tran", 1e-3, 1); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(5 * Math.Sin(args.Time * 10 * Math.PI), args.GetVoltage("in"), 1e-9); }; tran.Run(ckt); }
public void When_DelayTransient02_Expect_NoException() { var ckt = new Circuit( new VoltageSource("V1", "1", "0", new Sine(0, 5, 50, 0, 0, 90)), new VoltageDelay("BVD1", "2", "0", "1", "0", 1e-2), new Resistor("R1", "1", "0", 10), new Resistor("R2", "2", "0", 10) ); var tran = new Transient("tran", 1e-8, 1e-5); tran.Run(ckt); }
public void When_MultipleTransient_Expect_Reference() { /* * We test if the simulation can run twice on different circuits with * different number of equations. */ var cktA = new Circuit( new CurrentSource("I1", "0", "in", new Pulse(0, 1e-3, 0, 1e-15, 1, 10, 20)), new Resistor("R1", "in", "0", 1e9), new Capacitor("C1", "in", "0", 1e-6)); var cktB = new Circuit( new CurrentSource("I1", "0", "in", new Pulse(0, 1e-3, 0, 1e-15, 1, 10, 20)), new VoltageSource("V1", "in", "out", 0.0), new Resistor("R1", "in", "0", 1e9), new Capacitor("C1", "out", "0", 1e-6), new Capacitor("C2", "out", "0", 1e-6)); var tran = new Transient("tran", 1e-9, 1e-6); var a = true; tran.ExportSimulationData += (sender, args) => { if (a) { Assert.AreEqual(args.Time * 1e-3 / 1e-6, args.GetVoltage("in"), 1e-12); } else { Assert.AreEqual(args.Time * 1e-3 / 2e-6, args.GetVoltage("in"), 1e-12); } }; a = false; // Doing second circuit tran.Run(cktB); a = true; // Doing first circuit tran.Run(cktA); }
public void When_SimpleTransient_Expect_Reference(double vo, double va, double fc, double mdi, double fs, double phasec, double phases) { var ckt = new Circuit( new VoltageSource("V1", "a", "0", new SFFM(vo, va, fc, mdi, fs, phasec, phases))); var tran = new Transient("tran", 1e-6, 1); tran.ExportSimulationData += (sender, args) => { var time = args.Time; Assert.AreEqual(vo + va * Math.Sin(2.0 * Math.PI * fc * time + phasec * Math.PI / 180.0 + mdi * Math.Sin(2.0 * Math.PI * fs * time + phases * Math.PI / 180.0)), args.GetVoltage("a"), 1e-12); }; tran.Run(ckt); }
public void When_CurrentSourceReference_Expect_Reference() { var ckt = new Circuit( new CurrentSource("I1", "a", "0", new Sine(0, 1, 100)), new Resistor("R1", "a", "0", 1e3), new BehavioralVoltageSource("V1", "b", "0", "I(I1)")); var tran = new Transient("tran", 1e-3, 0.1); tran.ExportSimulationData += (sender, args) => { var expected = Math.Sin(2 * Math.PI * 100 * args.Time); var actual = args.GetVoltage("b"); Assert.AreEqual(expected, actual, 1e-9); }; tran.Run(ckt); }
public void When_DifferentialVoltage_Expect_Reference() { var ckt = new Circuit( new VoltageSource("V1", "a", "0", new Sine(0, 1, 100)), new VoltageSource("V2", "b", "0", new Sine(0, 2, 65)), new BehavioralCurrentSource("I1", "0", "out", "V(a,b)/2"), new Resistor("R1", "out", "0", 1)); var tran = new Transient("tran", 1e-6, 1e-3); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(0.5 * (args.GetVoltage("a") - args.GetVoltage("b")), args.GetVoltage("out"), 1e-12); }; tran.Run(ckt); }
/// <summary> /// Output for Matlab plotting /// </summary> /// <param name="sim">Simulation</param> /// <param name="ckt">Circuit</param> /// <param name="exports">Exports</param> /// <param name="references">References</param> protected void MatlabTransient(Transient sim, Circuit ckt, IEnumerable <Export <double> > exports, IEnumerable <double[]> references) { var refQuantity = new List <List <double> >(); var simQuantity = new List <List <double> >(); int index = 0; sim.ExportSimulationData += (sender, data) => { using (var exportsIt = exports.GetEnumerator()) using (var referencesIt = references.GetEnumerator()) { int cIndex = 0; while (exportsIt.MoveNext() && referencesIt.MoveNext()) { double actual = exportsIt.Current?.Value ?? throw new ArgumentNullException(); double expected = referencesIt.Current?[index] ?? throw new ArgumentNullException(); double tol = Math.Max(Math.Abs(actual), Math.Abs(expected)) * RelTol + AbsTol; // Add new series if (index == 0) { refQuantity.Add(new List <double>()); simQuantity.Add(new List <double>()); } refQuantity[cIndex].Add(expected); simQuantity[cIndex].Add(actual); Console.Write(expected.ToString() + ", "); } index++; } }; sim.Run(ckt); // Show the vectors foreach (var vec in refQuantity) { Console.WriteLine("v = [" + string.Join(",", vec) + "];"); } foreach (var vec in simQuantity) { Console.WriteLine("actual = [" + string.Join(",", vec) + "];"); } }
public void When_FixedEulerDerivative_Expect_Reference() { // Test a single derivative state var f = 100.0; var w = 2 * Math.PI * f; var tran = new Transient("tran", new FixedEuler { Step = 1e-7, StopTime = 1 / f }); var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Sine(0, 1, f)), // Fixed Euler has the worst accuracy, we only limit to an absolute error of 0.1. new DerivativeTester(time => w * Math.Cos(w * time), 0.0, 1e-3, 1e-1)); tran.Run(ckt); }
public void When_CapacitorTransient_Expect_Reference() { var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Sine(0, 1, 100)), new Capacitor("C1", "in", "0", 1e-6), new BehavioralCurrentSource("C2", "in", "0", "1u*ddt(V(in))")); var tran = new Transient("tran", 1e-6, 0.1); var reference = new RealPropertyExport(tran, "C1", "i"); var actual = new RealPropertyExport(tran, "C2", "i"); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(reference.Value, actual.Value, 1e-12); }; tran.Run(ckt); }
public void When_GearIntegral_Expect_Reference() { // Test a single derivative state var f = 100.0; var w = 2 * Math.PI * f; var tran = new Transient("tran", new Gear { InitialStep = 1e-9, MaxStep = 1e-5, StopTime = 1 / f }); var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Sine(0, 1, f)), // Fixed Euler has the worst accuracy, we only limit to an absolute error of 0.1. new IntegralTester(time => (1 - Math.Cos(w * time)) / w, 0, 1e-6, 1e-6)); tran.Run(ckt); }
public void When_PwlHasMinusTimeValue_Expect_Reference() { // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pwl(new double[] { -1.0, 1.0 }, new double[] { 0.0, 2.0 })), new Resistor("R1", "in", "0", 10.0) ); // Create the transient analysis var tran = new Transient("Tran 1", 1e-6, 1.0); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(args.Time < 1.0 ? 1.0 + args.Time : 2.0, args.GetVoltage("in"), 1e-12); }; tran.Run(ckt); }
public void When_FloatingRTransient_Expect_Reference() { // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", 10.0), new Resistor("R1", "in", "out", 10.0) ); // Create the transient analysis var tran = new Transient("Tran 1", 1e-6, 10.0); tran.ExportSimulationData += (sender, args) => { Assert.AreEqual(args.GetVoltage("out"), 10.0, 1e-12); }; tran.Run(ckt); }
public void When_FixedEuler_Expect_NoException() { // Create a circuit with a nonlinear component var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pulse(0, 5, 1e-6, 1e-6, 1e-6, 1e-5, 2e-5)), new NonlinearResistor("NLR1", "in", "out") .SetParameter("a", 100.0) .SetParameter("b", 0.7), new Capacitor("C1", "out", "0", 1.0e-9) ); // Create a transient analysis using Backward Euler with fixed timesteps var tran = new Transient("tran", 1e-7, 10e-5); tran.Configurations.Get <TimeConfiguration>().Method = new FixedEuler(); tran.Run(ckt); }
public void When_GearDerivative_Expect_Reference() { // Test a single derivative state var f = 100.0; var w = 2 * Math.PI * f; var tran = new Transient("tran", new Gear { InitialStep = 1e-9, MaxStep = 1e-5, StopTime = 1 / f }); var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Sine(0, 1, f)), // Trapezoidal integration allows for more accurate derivatives new DerivativeTester(time => w * Math.Cos(w * time), 0.0, 1e-3, 1e-3)); tran.Run(ckt); }
public void When_PwlHasManySawPoints_Expect_Reference() { var n = 10000; var pts = new Point[n]; for (var i = 0; i < n; i++) { pts[i] = new Point(i, i % 2); } // Create the circuit var ckt = new Circuit( new VoltageSource("V1", "in", "0", new Pwl() { Points = pts }), new Resistor("R1", "in", "0", 10.0) ); // Create the transient analysis var tran = new Transient("Tran 1", 1e-2, n - 1); tran.ExportSimulationData += (sender, args) => { int integer = (int)args.Time; if (args.Time == integer) { Assert.AreEqual(integer % 2, args.GetVoltage("in"), 1e-12); } else { if (integer % 2 == 0) { Assert.AreEqual(args.Time - integer, args.GetVoltage("in"), 1e-12); } else { Assert.AreEqual(1 - (args.Time - integer), args.GetVoltage("in"), 1e-12); } } }; tran.Run(ckt); }
public void When_RCFilterConstantTransient_Expect_Reference() { // Create the circuit Circuit ckt = new Circuit( new VoltageSource("V1", "in", "0", 10.0), new Resistor("R1", "in", "out", 10), new Capacitor("C1", "out", "0", 20) ); // Create the transient analysis Transient tran = new Transient("tran 1", 1.0, 10.0); tran.ParameterSets.Get <TimeConfiguration>().InitTime = 0.0; tran.OnExportSimulationData += (sender, args) => { Assert.AreEqual(args.GetVoltage("out"), 10.0, 1e-12); }; tran.Run(ckt); }