Пример #1
0
        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);
            }
        }
 public void ClearSchematic()
 {
     Schematic     = null;
     SchematicPath = "";
     circuit       = null;
     InteractiveComponents.Clear();
 }
Пример #3
0
        public double RunTest(Circuit.Circuit C, Simulation S, Func <double, double> Vin, int Samples, string Name)
        {
            double t0 = (double)S.Time;
            double T  = S.TimeStep;

            int N = 353;

            double[] input = new double[N];

            List <List <double> > output  = S.Output.Select(i => new List <double>(Samples)).ToList();
            List <double[]>       buffers = S.Output.Select(i => new double[N]).ToList();

            double time    = 0.0;
            int    samples = 0;
            double t       = 0;

            for (; samples < Samples; samples += N)
            {
                for (int n = 0; n < N; ++n, t += T)
                {
                    input[n] = Vin(t);
                }

                long a = Timer.Counter;
                S.Run(input, buffers);
                time += Timer.Delta(a);

                for (int i = 0; i < S.Output.Count(); ++i)
                {
                    output[i].AddRange(buffers[i]);
                }
            }
            simulateTime += time;

            int t1 = Math.Min(samples, 4000);

            Log.WriteLine("Performance {0}", Quantity.ToString(samples / time, Units.Hz));

            Plot p = new Plot()
            {
                Title  = Name,
                Width  = 800,
                Height = 400,
                x0     = t0,
                x1     = T * t1,
                xLabel = "Time (s)",
                yLabel = "Voltage (V)",
            };

            p.Series.AddRange(output.Select((i, j) => new Scatter(
                                                i.Take(t1)
                                                .Select((k, n) => new KeyValuePair <double, double>(n * T, k)).ToArray())
            {
                Name = S.Output.ElementAt(j).ToString()
            }));
            return(samples / time);
        }
Пример #4
0
 private static Expression FindInput(Circuit.Circuit C)
 {
     return(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());
 }
Пример #5
0
 private static Expression FindInput(Circuit.Circuit C)
 {
     return(C.Components.OfType <Input>()
            .Select(i => i.In)
            // If there are no inputs, just make a dummy.
            .DefaultIfEmpty("V[t]")
            // Require exactly one input.
            .Single());
 }
Пример #6
0
 public double Run(string FileName, Func <double, double> Vin)
 {
     Circuit.Circuit C = Schematic.Load(FileName, Log).Build();
     C.Name = System.IO.Path.GetFileNameWithoutExtension(FileName);
     return(Run(
                C,
                Vin,
                C.Components.OfType <Input>().Select(i => Expression.Parse(i.Name + "[t]")).DefaultIfEmpty("V[t]").SingleOrDefault(),
                C.Nodes.Select(i => i.V)));
 }
        public void LoadSchematic(string path)
        {
            Schematic newSchematic = Circuit.Schematic.Load(path);

            Circuit.Circuit circuit = newSchematic.Build();

            SetCircuit(circuit);

            Schematic = newSchematic;

            SchematicPath = path;
        }
        void SetCircuit(Circuit.Circuit circuit)
        {
            this.circuit = circuit;

            InteractiveComponents.Clear();

            Dictionary <string, ButtonWrapper> buttonGroups = new Dictionary <string, ButtonWrapper>();

            foreach (Circuit.Component i in circuit.Components)
            {
                if (i is IPotControl)
                {
                    InteractiveComponents.Add(new PotWrapper((i as IPotControl), i.Name));
                }
                else if (i is IButtonControl)
                {
                    IButtonControl button = (i as IButtonControl);

                    ButtonWrapper wrapper = null;

                    if (string.IsNullOrEmpty(button.Group))
                    {
                        wrapper = new ButtonWrapper(i.Name);
                        InteractiveComponents.Add(wrapper);
                    }
                    else if (buttonGroups.ContainsKey(button.Group))
                    {
                        wrapper = buttonGroups[button.Group];
                    }
                    else
                    {
                        wrapper = new ButtonWrapper(button.Group);

                        buttonGroups[button.Group] = wrapper;

                        InteractiveComponents.Add(wrapper);
                    }

                    wrapper.AddButton(button);
                }
            }

            needRebuild = true;
        }
Пример #9
0
        static void Main(string[] args)
        {
            bool test      = args.Contains("--test");
            bool benchmark = args.Contains("--benchmark");
            bool plot      = args.Contains("--plot");

            Log log = new ConsoleLog()
            {
                Verbosity = MessageType.Info
            };
            Test tester = new Test();

            foreach (string i in args.Where(i => !i.StartsWith("--")))
            {
                foreach (string File in Globber.Glob(i))
                {
                    System.Console.WriteLine(File);
                    Circuit.Circuit C = Schematic.Load(File, log).Build();
                    C.Name = Path.GetFileNameWithoutExtension(File);
                    if (test)
                    {
                        Dictionary <Expression, List <double> > outputs =
                            tester.Run(C, t => Harmonics(t, 0.5, 82, 2), SampleRate, Samples, Oversample, Iterations);
                        if (plot)
                        {
                            tester.PlotAll(C.Name, outputs);
                        }
                    }
                    if (benchmark)
                    {
                        tester.Benchmark(C, t => Harmonics(t, 0.5, 82, 2), SampleRate, Oversample, Iterations);
                    }
                    System.Console.WriteLine("");
                }
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
 /// <summary>
 /// Begin analysis of a new context.
 /// </summary>
 /// <param name="Name"></param>
 public void PushContext(string Name)
 {
     context = new Circuit(context, Name);
 }
Пример #12
0
        /// <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);
        }
Пример #13
0
 public Circuit(Circuit Parent, string Name)
 {
     parent = Parent;  name = Name;
 }
Пример #14
0
 public double Run(string FileName, Func <double, double> Vin, Expression Input, IEnumerable <Expression> Plots)
 {
     Circuit.Circuit C = Schematic.Load(FileName, Log).Build();
     C.Name = System.IO.Path.GetFileNameWithoutExtension(FileName);
     return(Run(C, Vin, Input, Plots));
 }
Пример #15
0
        void SetCircuit(Circuit.Circuit circuit)
        {
            this.circuit = circuit;

            InteractiveComponents.Clear();

            Dictionary <string, ButtonWrapper> buttonGroups = new Dictionary <string, ButtonWrapper>();
            Dictionary <string, PotWrapper>    potGroups    = new Dictionary <string, PotWrapper>();

            foreach (Circuit.Component i in circuit.Components)
            {
                if (i is IPotControl pot)
                {
                    if (string.IsNullOrEmpty(pot.Group))
                    {
                        InteractiveComponents.Add(new PotWrapper(pot, i.Name));
                    }
                    else if (potGroups.TryGetValue(pot.Group, out var wrapper))
                    {
                        wrapper.AddSection(pot);
                    }
                    else
                    {
                        wrapper = new PotWrapper(pot, pot.Group);
                        potGroups.Add(pot.Group, wrapper);
                        InteractiveComponents.Add(wrapper);
                    }
                }
                else if (i is IButtonControl button)
                {
                    ButtonWrapper wrapper;
                    if (string.IsNullOrEmpty(button.Group))
                    {
                        if (button.NumPositions == 2)
                        {
                            wrapper = new DoubleThrowWrapper(button, i.Name);
                            InteractiveComponents.Add(wrapper);
                        }
                        else
                        {
                            wrapper = new MultiThrowWrapper(button, i.Name);
                            InteractiveComponents.Add(wrapper);
                        }
                    }
                    else if (buttonGroups.ContainsKey(button.Group))
                    {
                        wrapper = buttonGroups[button.Group];
                        wrapper.AddSection(button);
                    }
                    else
                    {
                        if (button.NumPositions == 2)
                        {
                            wrapper = new DoubleThrowWrapper(button, button.Group);
                        }
                        else
                        {
                            wrapper = new MultiThrowWrapper(button, i.Name);
                        }

                        buttonGroups[button.Group] = wrapper;

                        InteractiveComponents.Add(wrapper);
                    }
                }
            }

            needRebuild = true;
        }
Пример #16
0
        public LiveSimulation(Schematic Simulate, Audio.Device Device, Audio.Channel[] Inputs, Audio.Channel[] Outputs)
        {
            try
            {
                InitializeComponent();

                // Make a clone of the schematic so we can mess with it.
                var clone = Circuit.Schematic.Deserialize(Simulate.Serialize(), Log);
                clone.Elements.ItemAdded   += OnElementAdded;
                clone.Elements.ItemRemoved += OnElementRemoved;
                Schematic = new SimulationSchematic(clone);
                Schematic.SelectionChanged += OnProbeSelected;

                // Build the circuit from the schematic.
                circuit = Schematic.Schematic.Build(Log);

                // Create the input and output controls.
                IEnumerable <Circuit.Component> components = circuit.Components;

                // Create audio input channels.
                for (int i = 0; i < Inputs.Length; ++i)
                {
                    InputChannels.Add(new InputChannel(i)
                    {
                        Name = Inputs[i].Name
                    });
                }

                ComputerAlgebra.Expression speakers = 0;

                foreach (Circuit.Component i in components)
                {
                    Symbol S = i.Tag as Symbol;
                    if (S == null)
                    {
                        continue;
                    }

                    SymbolControl tag = (SymbolControl)S.Tag;
                    if (tag == null)
                    {
                        continue;
                    }

                    // Create potentiometers.
                    if (i is IPotControl potentiometer)
                    {
                        var potControl = new PotControl()
                        {
                            Width      = 80,
                            Height     = 80,
                            Opacity    = 0.5,
                            FontSize   = 15,
                            FontWeight = FontWeights.Bold,
                        };
                        Schematic.Overlays.Children.Add(potControl);
                        Canvas.SetLeft(potControl, Canvas.GetLeft(tag) - potControl.Width / 2 + tag.Width / 2);
                        Canvas.SetTop(potControl, Canvas.GetTop(tag) - potControl.Height / 2 + tag.Height / 2);

                        var binding = new Binding
                        {
                            Source = potentiometer,
                            Path   = new PropertyPath("(0)", typeof(IPotControl).GetProperty(nameof(IPotControl.PotValue))),
                            Mode   = BindingMode.TwoWay,
                            NotifyOnSourceUpdated = true
                        };

                        potControl.SetBinding(PotControl.ValueProperty, binding);

                        potControl.AddHandler(Binding.SourceUpdatedEvent, new RoutedEventHandler((o, args) =>
                        {
                            if (!string.IsNullOrEmpty(potentiometer.Group))
                            {
                                foreach (var p in components.OfType <IPotControl>().Where(p => p != potentiometer && p.Group == potentiometer.Group))
                                {
                                    p.PotValue = (o as PotControl).Value;
                                }
                            }
                            UpdateSimulation(false);
                        }));

                        potControl.MouseEnter += (o, e) => potControl.Opacity = 0.95;
                        potControl.MouseLeave += (o, e) => potControl.Opacity = 0.5;
                    }

                    // Create Buttons.
                    if (i is IButtonControl b)
                    {
                        Button button = new Button()
                        {
                            Width      = tag.Width,
                            Height     = tag.Height,
                            Opacity    = 0.5,
                            Background = Brushes.White,
                        };
                        Schematic.Overlays.Children.Add(button);
                        Canvas.SetLeft(button, Canvas.GetLeft(tag));
                        Canvas.SetTop(button, Canvas.GetTop(tag));

                        button.Click += (o, e) =>
                        {
                            b.Click();
                            // Click all the buttons in the group.
                            if (!string.IsNullOrEmpty(b.Group))
                            {
                                foreach (var j in components.OfType <IButtonControl>().Where(x => x != b && x.Group == b.Group))
                                {
                                    j.Click();
                                }
                            }
                            UpdateSimulation(true);
                        };

                        button.MouseEnter += (o, e) => button.Opacity = 0.95;
                        button.MouseLeave += (o, e) => button.Opacity = 0.5;
                    }

                    if (i is Speaker output)
                    {
                        speakers += output.Out;
                    }

                    // Create input controls.
                    if (i is Input input)
                    {
                        tag.ShowText = false;

                        ComboBox combo = new ComboBox()
                        {
                            Width             = 80,
                            Height            = 24,
                            Opacity           = 0.5,
                            IsEditable        = true,
                            SelectedValuePath = "Tag",
                        };

                        foreach (InputChannel j in InputChannels)
                        {
                            combo.Items.Add(new ComboBoxItem()
                            {
                                Tag     = j,
                                Content = j.Name
                            });
                        }

                        Schematic.Overlays.Children.Add(combo);
                        Canvas.SetLeft(combo, Canvas.GetLeft(tag) - combo.Width / 2 + tag.Width / 2);
                        Canvas.SetTop(combo, Canvas.GetTop(tag) - combo.Height / 2 + tag.Height / 2);

                        ComputerAlgebra.Expression In = input.In;
                        inputs[In] = new SignalChannel(0);

                        combo.SelectionChanged += (o, e) =>
                        {
                            if (combo.SelectedItem != null)
                            {
                                ComboBoxItem it = (ComboBoxItem)combo.SelectedItem;
                                inputs[In] = new InputChannel(((InputChannel)it.Tag).Index);
                            }
                        };

                        combo.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler((o, e) =>
                        {
                            try
                            {
                                inputs[In] = new SignalChannel(ComputerAlgebra.Expression.Parse(combo.Text));
                            }
                            catch (Exception)
                            {
                                // If there is an error in the expression, zero out the signal.
                                inputs[In] = new SignalChannel(0);
                            }
                        }));

                        if (combo.Items.Count > 0)
                        {
                            combo.SelectedItem = combo.Items[0];
                        }
                        else
                        {
                            combo.Text = "0 V";
                        }

                        combo.MouseEnter += (o, e) => combo.Opacity = 0.95;
                        combo.MouseLeave += (o, e) => combo.Opacity = 0.5;
                    }
                }

                // Create audio output channels.
                for (int i = 0; i < Outputs.Length; ++i)
                {
                    OutputChannel c = new OutputChannel(i)
                    {
                        Name = Outputs[i].Name, Signal = speakers
                    };
                    c.PropertyChanged += (o, e) => { if (e.PropertyName == "Signal")
                                                     {
                                                         RebuildSolution();
                                                     }
                    };
                    OutputChannels.Add(c);
                }


                // Begin audio processing.
                if (Inputs.Any() || Outputs.Any())
                {
                    stream = Device.Open(ProcessSamples, Inputs, Outputs);
                }
                else
                {
                    stream = new NullStream(ProcessSamples);
                }

                ContentRendered += (o, e) => RebuildSolution();

                Closed += (s, e) => stream.Stop();

                timer = new System.Timers.Timer()
                {
                    Interval  = 100,
                    AutoReset = true,
                    Enabled   = true,
                };
                timer.Elapsed += timer_Elapsed;
                timer.Start();
            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Пример #17
0
        /// <summary>
        /// End analysis of the current context.
        /// </summary>
        public void PopContext()
        {
            // Evaluate the definitions from the context for the equations and add the results to the analysis.
            foreach (Equal i in context.Equations)
            {
                Equal ei = (Equal)Evaluate(i, context.Definitions);
                if (!equations.Contains(ei))
                    equations.Add(ei);
            }
            // And the KCL equations.
            foreach (KeyValuePair<Expression, Expression> i in context.Kcl)
                AddKcl(kcl, i.Key, Evaluate(i.Value, context.Definitions));
            // And the initial conditions.
            initialConditions.AddRange(context.InitialConditions.Evaluate(context.Definitions).OfType<Arrow>());

            foreach (Node i in context.Nodes)
                i.EndAnalysis();

            context = context.Parent;
        }
Пример #18
0
        public double RunTest(Circuit.Circuit C, Simulation S, Func<double, double> Vin, int Samples, string Name)
        {
            double t0 = (double)S.Time;
            double T = S.TimeStep;

            int N = 353;
            double[] input = new double[N];

            List<List<double>> output = S.Output.Select(i => new List<double>(Samples)).ToList();
            List<double[]> buffers = S.Output.Select(i => new double[N]).ToList();

            double time = 0.0;
            int samples = 0;
            double t = 0;
            for (; samples < Samples; samples += N)
            {
                for (int n = 0; n < N; ++n, t += T)
                    input[n] = Vin(t);

                long a = Timer.Counter;
                S.Run(input, buffers);
                time += Timer.Delta(a);

                for (int i = 0; i < S.Output.Count(); ++i)
                    output[i].AddRange(buffers[i]);
            }
            simulateTime += time;

            int t1 = Math.Min(samples, 4000);

            Log.WriteLine("Performance {0}", Quantity.ToString(samples / time, Units.Hz));

            Plot p = new Plot()
            {
                Title = Name,
                Width = 800,
                Height = 400,
                x0 = t0,
                x1 = T * t1,
                xLabel = "Time (s)",
                yLabel = "Voltage (V)",
            };

            p.Series.AddRange(output.Select((i, j) => new Scatter(
                i.Take(t1)
                .Select((k, n) => new KeyValuePair<double, double>(n * T, k)).ToArray()) { Name = S.Output.ElementAt(j).ToString() }));
            return samples / time;
        }
Пример #19
0
        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;
        }