public double Run(Circuit.Circuit C, Func <double, double> Vin, Expression Input, IEnumerable <Expression> Plots) { long a = Timer.Counter; Analysis analysis = C.Analyze(); TransientSolution TS = TransientSolution.Solve(analysis, (Real)1 / (SampleRate * Oversample), Log); analysisTime += Timer.Delta(a); Simulation S = new Simulation(TS) { Oversample = Oversample, Iterations = Iterations, Log = Log, Input = new[] { Input }, Output = Plots, }; Log.WriteLine(""); if (Samples > 0) { return(RunTest( C, S, Vin, Samples, C.Name)); } else { return(0.0); } }
private void UpdateSimulation(bool Rebuild) { int id = Interlocked.Increment(ref update); new Task(() => { ComputerAlgebra.Expression h = (ComputerAlgebra.Expression) 1 / (stream.SampleRate * Oversample); TransientSolution s = Circuit.TransientSolution.Solve(circuit.Analyze(), h, Rebuild ? (ILog)Log : new NullLog()); lock (sync) { if (id > clock) { if (Rebuild) { simulation = new Simulation(s) { Log = Log, Input = inputs.Keys.ToArray(), Output = probes.Select(i => i.V).Concat(OutputChannels.Select(i => i.Signal)).ToArray(), Oversample = Oversample, Iterations = Iterations, }; } else { simulation.Solution = s; clock = id; } } } }).Start(scheduler); }
private void RebuildSolution() { lock (sync) { simulation = null; ProgressDialog.RunAsync(this, "Building circuit solution...", () => { try { ComputerAlgebra.Expression h = (ComputerAlgebra.Expression) 1 / (stream.SampleRate * Oversample); TransientSolution solution = Circuit.TransientSolution.Solve(circuit.Analyze(), h, Log); simulation = new Simulation(solution) { Log = Log, Input = inputs.Keys.ToArray(), Output = probes.Select(i => i.V).Concat(OutputChannels.Select(i => i.Signal)).ToArray(), Oversample = Oversample, Iterations = Iterations, }; } catch (Exception Ex) { Log.WriteException(Ex); } }); } }
public Dictionary <Expression, List <double> > Run( Circuit.Circuit C, Func <double, double> Vin, int SampleRate, int Samples, int Oversample, int Iterations, Expression Input = null, IEnumerable <Expression> Outputs = null) { Analysis analysis = C.Analyze(); TransientSolution TS = TransientSolution.Solve(analysis, (Real)1 / (SampleRate * Oversample)); // By default, pass Vin to each input of the circuit. if (Input == null) { Input = C.Components.Where(i => i is Input) .Select(i => Component.DependentVariable(i.Name, Component.t)) // If there are no inputs, just make a dummy. .DefaultIfEmpty("V[t]") // Require exactly one input. .Single(); } // By default, produce every node of the circuit as output. if (Outputs == null) { Outputs = C.Nodes.Select(i => i.V); } Simulation S = new Simulation(TS) { Oversample = Oversample, Iterations = Iterations, Input = new[] { Input }, Output = Outputs, }; Dictionary <Expression, List <double> > outputs = S.Output.ToDictionary(i => i, i => new List <double>(Samples)); double T = S.TimeStep; double t = 0; Random rng = new Random(); int remaining = Samples; while (remaining > 0) { // Using a varying number of samples on each call to S.Run int N = Math.Min(remaining, rng.Next(1000, 10000)); double[] inputBuffer = new double[N]; List <double[]> outputBuffers = S.Output.Select(i => new double[N]).ToList(); for (int n = 0; n < N; ++n, t += T) { inputBuffer[n] = Vin(t); } S.Run(inputBuffer, outputBuffers); for (int i = 0; i < S.Output.Count(); ++i) { outputs[S.Output.ElementAt(i)].AddRange(outputBuffers[i]); } remaining -= N; } return(outputs); }
/// <summary> /// Benchmark a circuit simulation. /// By default, benchmarks producing the sum of all output components. /// </summary> /// <returns>The rate at which the circuit simulated, in samples per second.</returns> public void Benchmark( Circuit.Circuit C, Func <double, double> Vin, int SampleRate, int Oversample, int Iterations, Expression Input = null, IEnumerable <Expression> Outputs = null) { Analysis analysis = null; double analyzeTime = Benchmark(1, () => analysis = C.Analyze()); System.Console.WriteLine("Circuit.Analyze time: {0:G3} ms", analyzeTime * 1000); TransientSolution TS = null; double solveTime = Benchmark(1, () => TS = TransientSolution.Solve(analysis, (Real)1 / (SampleRate * Oversample))); System.Console.WriteLine("TransientSolution.Solve time: {0:G3} ms", solveTime * 1000); // By default, pass Vin to each input of the circuit. if (Input == null) { Input = FindInput(C); } // By default, produce every node of the circuit as output. if (Outputs == null) { Expression sum = 0; foreach (Speaker i in C.Components.Where(i => i is Speaker)) { sum += Component.DependentVariable(i.Name, Component.t); } Outputs = new[] { sum }; } Simulation S = null; double simTime = Benchmark(1, () => S = new Simulation(TS) { Oversample = Oversample, Iterations = Iterations, Input = new[] { Input }, Output = Outputs, }); System.Console.WriteLine("Simulation.Simulation time: {0} ms", simTime * 1000); int N = 1000; double[] inputBuffer = new double[N]; List <double[]> outputBuffers = Outputs.Select(i => new double[N]).ToList(); double T = 1.0 / SampleRate; double t = 0; double runTime = Benchmark(3, () => { // This is counting the cost of evaluating Vin during benchmarking... for (int n = 0; n < N; ++n, t += T) { inputBuffer[n] = Vin(t); } S.Run(inputBuffer, outputBuffers); }); double rate = N / runTime; System.Console.WriteLine("{0:G3} kHz, {1:G3}x real time", rate / 1000, rate / SampleRate); }
/// <summary> /// Update the simulation asynchronously /// </summary> /// <param name="rebuild">Whether a full simulation rebuild is required</param> void UpdateSimulation(bool rebuild) { int id = Interlocked.Increment(ref update); new Task(() => { try { Analysis analysis = circuit.Analyze(); TransientSolution ts = TransientSolution.Solve(analysis, (Real)1 / (sampleRate * oversample)); lock (sync) { if (id > clock) { if (rebuild) { Expression inputExpression = circuit.Components.OfType <Input>().Select(i => i.In).SingleOrDefault(); if (inputExpression == null) { simulationUpdateException = new NotSupportedException("Circuit has no inputs."); } else { IEnumerable <Speaker> speakers = circuit.Components.OfType <Speaker>(); Expression outputExpression = 0; // Output is voltage drop across the speakers foreach (Speaker speaker in speakers) { outputExpression += speaker.Out; } if (outputExpression.EqualsZero()) { simulationUpdateException = new NotSupportedException("Circuit has no speaker outputs."); } else { simulation = new Simulation(ts) { Oversample = oversample, Iterations = iterations, Input = new[] { inputExpression }, Output = new[] { outputExpression } }; } } } else { simulation.Solution = ts; clock = id; } } } } catch (Exception ex) { simulationUpdateException = ex; } }).Start(scheduler); }