private void UpdateSimulation(bool Rebuild) { int id = Interlocked.Increment(ref update); new Task(() => { ComputerAlgebra.Expression h = (ComputerAlgebra.Expression) 1 / (stream.SampleRate * Oversample); Circuit.TransientSolution s = Circuit.TransientSolution.Solve(circuit.Analyze(), h, Rebuild ? (ILog)Log : new NullLog()); lock (sync) { if (id > clock) { if (Rebuild) { simulation = new Circuit.Simulation(s) { Log = Log, Input = inputs.Keys, Output = probes.Select(i => i.V).Concat(OutputChannels.Select(i => i.Signal)), 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); Circuit.TransientSolution solution = Circuit.TransientSolution.Solve(circuit.Analyze(), h, Log); simulation = new Circuit.Simulation(solution) { Log = Log, Input = inputs.Keys, Output = probes.Select(i => i.V).Concat(OutputChannels.Select(i => i.Signal)), Oversample = Oversample, Iterations = Iterations, }; } catch (Exception Ex) { Log.WriteException(Ex); } }); } }
public static void TestSymbolism() { // Create some constants. ComputerAlgebra.Expression A = 2; ComputerAlgebra.Constant B = ComputerAlgebra.Constant.New(3); // Create some variables. ComputerAlgebra.Expression x = "x"; Variable y = Variable.New("y"); // Create basic expression with operator overloads. ComputerAlgebra.Expression f = A * x + B * y + 4; // This expression uses the implicit conversion from string to // Expression, which parses the string. ComputerAlgebra.Expression g = "5*x + C*y + 8"; // Create a system of equations from the above expressions. var system = new List <Equal>() { Equal.New(f, 0), Equal.New(g, 0), }; // We can now solve the system of equations for x and y. Since the // equations have a variable 'C', the solutions will not be // constants. List <Arrow> solutions = system.Solve(x, y); Debug.WriteLine("The solutions are:"); foreach (Arrow i in solutions) { Debug.WriteLine(i.ToString()); } }
private void BindSignal_Click(object sender, RoutedEventArgs e) { OutputChannel ch = (OutputChannel)((FrameworkElement)sender).Tag; SchematicTool tool = Schematic.Tool; Schematic.Tool = new FindRelevantTool(Schematic) { Relevant = (x) => x is Circuit.Symbol && ((Circuit.Symbol)x).Component is Circuit.TwoTerminal, Clicked = (x) => { if (x.Any()) { ComputerAlgebra.Expression init = (Keyboard.Modifiers & ModifierKeys.Control) != 0 ? ch.Signal : 0; ch.Signal = x.OfType <Circuit.Symbol>() .Select(i => i.Component) .OfType <Circuit.TwoTerminal>() .Aggregate(init, (sum, c) => sum + c.V); } Schematic.Tool = tool; } }; }
public LiveSimulation(Circuit.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. Circuit.Schematic 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) { Circuit.Symbol S = i.Tag as Circuit.Symbol; if (S == null) { continue; } SymbolControl tag = (SymbolControl)S.Tag; if (tag == null) { continue; } // Create potentiometers. Circuit.IPotControl c = i as Circuit.IPotControl; if (c != null) { PotControl pot = new PotControl() { Width = 80, Height = 80, Opacity = 0.5, FontSize = 15, FontWeight = FontWeights.Bold, }; Schematic.overlays.Children.Add(pot); Canvas.SetLeft(pot, Canvas.GetLeft(tag) - pot.Width / 2 + tag.Width / 2); Canvas.SetTop(pot, Canvas.GetTop(tag) - pot.Height / 2 + tag.Height / 2); pot.Value = c.PotValue; pot.ValueChanged += x => { c.PotValue = x; UpdateSimulation(false); }; pot.MouseEnter += (o, e) => pot.Opacity = 0.95; pot.MouseLeave += (o, e) => pot.Opacity = 0.5; } // Create Buttons. Circuit.IButtonControl b = i as Circuit.IButtonControl; if (b != null) { 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) => { // Click all the buttons in the group. foreach (Circuit.IButtonControl j in components.OfType <Circuit.IButtonControl>().Where(x => x.Group == b.Group)) { j.Click(); } UpdateSimulation(true); }; button.MouseEnter += (o, e) => button.Opacity = 0.95; button.MouseLeave += (o, e) => button.Opacity = 0.5; } Circuit.Speaker output = i as Circuit.Speaker; if (output != null) { speakers += output.V; } // Create input controls. Circuit.Input input = i as Circuit.Input; if (input != null) { 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 V = Circuit.Component.DependentVariable(input.Name, Circuit.Component.t); inputs[V] = new SignalChannel(0); combo.SelectionChanged += (o, e) => { if (combo.SelectedItem != null) { ComboBoxItem it = (ComboBoxItem)combo.SelectedItem; inputs[V] = new InputChannel(((InputChannel)it.Tag).Index); } }; combo.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler((o, e) => { try { inputs[V] = new SignalChannel(Circuit.Quantity.Parse(combo.Text, Circuit.Units.V)); } catch (Exception) { // If there is an error in the expression, zero out the signal. inputs[V] = 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(); } catch (Exception Ex) { MessageBox.Show(Ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } }
public SignalChannel(ComputerAlgebra.Expression Signal) { signal = Signal.Compile <Func <double, double> >(Circuit.Component.t); }
public static void GetAllSheetFormulas() { // this will return a line for each equation on the current worksheet where the cell reference is assumed to be a variable // iterate through used range Excel.Application app = (Excel.Application)ExcelDnaUtil.Application; Excel.Worksheet sht = (Excel.Worksheet)app.ActiveSheet; Excel.Range usedRange = sht.UsedRange; var exprs = new List <ComputerAlgebra.Expression>(); var system = new List <Equal>(); var constants = new List <Arrow>(); foreach (Excel.Range rng in usedRange.Cells) { if ((bool)rng.HasFormula) { // if the cell has a formula, obtain the math equation for it Debug.WriteLine($"{rng.Address} has formula"); string formula = rng.Formula.ToString(); Debug.WriteLine($"formula: {formula}"); // remove the equal sign formula = formula.Substring(1); Debug.WriteLine($"formula: {formula}"); // take that thing and remove the leading = sign // TODO: anything required for the $C$2 names? // create an expression, and an equal equation // add to the systme of equations ComputerAlgebra.Expression thisCell = formula; Debug.WriteLine($"parsed expr: {thisCell.ToPrettyString()}"); exprs.Add(thisCell); //system.Add(Equal.New(thisCell, 0)); } else if (rng.Value.ToString() != "") { // if the cell is not blank process it Debug.WriteLine($"{rng.Address} is constant"); // create an arrow function for the constant Arrow thisCell = Arrow.New(rng.Address.Replace("$", ""), rng.Value.ToString()); Debug.Print($"arrow func: {thisCell.ToPrettyString()}"); constants.Add(thisCell); } } // run through the exprs and sub in the arrows (constants) foreach (var expr in exprs) { var evalExpr = expr.Evaluate(constants); Debug.WriteLine($"eval expr: {expr.ToPrettyString()} \t->\t {evalExpr.ToPrettyString()}"); } }