public List <Place> StartEquilibrate(List <SampleValue> inSamples, double fortime, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: EQUILIBRATE Start " + Style.FormatSequence(inSamples, ", ", x => x.FormatSymbol(style)) + " for " + style.FormatDouble(fortime)); List <Place> goBacks = new List <Place> { }; List <Place>[] routes = new List <Place> [inSamples.Count]; for (int i = 0; i < inSamples.Count; i++) { string toZone = (inSamples[i].Temperature() < KDeviceHandler.coldTemperature) ? "mixing" : (inSamples[i].Temperature() > KDeviceHandler.hotTemperature) ? "hot" : "warm"; Place goBack = placement.PlaceOf(inSamples[i], style); goBacks.Add(goBack); Place place = FreePlaceInColumn(zone[toZone], minRow: goBack.Row(), currentlyAt: goBack, skipNo: 0); routes[i] = placement.PathHorFirst(placement.PlaceOf(inSamples[i], style), place); } placement.FollowRoutes(routes, clearance: 1, style); device.dropletColor = dropletColorGrey; device.dropletBiggieColor = dropletColorGrey; KGui.gui.GuiDeviceUpdate(); return(goBacks); }
// Device button private void DeviceButton() { guiControls.onOffDevice.SetImage("icons8device_OFF_48x48"); guiControls.onOffDevice.OnClick( (object sender, EventArgs e) => { CloseOpenMenu(); if (!KDeviceHandler.Exists()) { KDeviceHandler.Start(30, 100); guiControls.MicrofluidicsOn(); guiControls.onOffDevice.SetImage("icons8device_ON_48x48"); guiControls.onOffDeviceView.Visible(true); guiControls.onOffDeviceView.Selected(true); } else { if (!Exec.IsExecuting()) { guiControls.onOffDeviceView.Visible(false); guiControls.MicrofluidicsOff(); guiControls.onOffDevice.SetImage("icons8device_OFF_48x48"); KDeviceHandler.Stop(); } } }); guiControls.onOffDevice.Visible(true); guiControls.onOffDevice.Enabled(true); }
public void FollowRoute(List <Place> route, int clearance, Style style, bool log = true) { Place current = null; foreach (Place next in route) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } if (current == null) { current = next; // starting place } else { if (CanStepTo(current, next, clearance)) { Step(StepDirection(current, next, style), current, next, style); current = next; } else { throw new Error("ERROR: Droplet FollowRoute failed"); } } } }
public void Split(List <SampleValue> outSamples, SampleValue inSample, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: SPLIT " + Style.FormatSequence(outSamples, ", ", x => x.FormatSymbol(style)) + " = " + inSample.FormatSymbol(style)); Place[,] area = FreeAreaInColumn(zone["mixing"], minRow: placement.PlaceOf(inSample, style).Row(), rows: 1, cols: 2 * outSamples.Count - 1); // find free columns in "mixing" block, on the same row placement.MoveHorFirst(inSample, area[0, 0], clearance: 1, style); double volume = inSample.Volume(); for (int i = outSamples.Count - 1; i >= 1; i--) { volume = volume - outSamples[i].Volume(); SampleValue tempSample = new SampleValue(inSample.symbol, null, new NumberValue(volume), new NumberValue(1), true); placement.SplitHor(tempSample, outSamples[i], area[0, 0], area[0, 1], style); placement.FollowRoute(placement.PathHorFirst(placement.PlaceOf(outSamples[i], style), area[0, 2 * i]), clearance: 0, style); } placement.Clear(area[0, 0], style, log: false); placement.Place(outSamples[0], area[0, 0], style, log: false); List <Place>[] routes = new List <Place> [outSamples.Count]; for (int i = 0; i < outSamples.Count; i++) { Place place = FreePlaceInColumn(zone["staging"], minRow: 0, currentlyAt: area[0, 2 * i], skipNo: i); routes[i] = placement.PathVerFirst(placement.PlaceOf(outSamples[i], style), place); } placement.FollowRoutes(routes, clearance: 1, style); }
public void Mix(SampleValue outSample, List <SampleValue> inSamples, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: MIX " + outSample.FormatSymbol(style) + " = " + Style.FormatSequence(inSamples, ", ", x => x.FormatSymbol(style))); Place[,] area = FreeAreaInColumn(zone["mixing"], minRow: placement.PlaceOf(inSamples[0], style).Row(), rows: 1, cols: 2 * inSamples.Count - 1); // find free columns in "mixing" block, on the same row List <Place>[] routes = new List <Place> [inSamples.Count]; for (int i = 0; i < inSamples.Count; i++) { routes[i] = placement.PathHorFirst(placement.PlaceOf(inSamples[i], style), area[0, 2 * i]); } placement.FollowRoutes(routes, clearance: 1, style); for (int i = 1; i < inSamples.Count; i++) { placement.FollowRoute(placement.PathHorFirst(placement.PlaceOf(inSamples[i], style), area[0, 1]), clearance: 0, style); SampleValue accumulator = placement.SampleOf(area[0, 0]); SampleValue tempSample = new SampleValue(outSample.symbol, null, new NumberValue(accumulator.Volume() + inSamples[i].Volume()), new NumberValue(1), true); placement.MixHor(tempSample, area[0, 0], area[0, 1], style); } placement.Clear(area[0, 0], style, log: false); placement.Place(outSample, area[0, 0], style, log: false); Place staging = FreePlaceInColumn(zone["staging"], minRow: 0, currentlyAt: area[0, 0], skipNo: 0); placement.MoveVerFirst(outSample, staging, clearance: 1, style); }
public void FollowRoutes(List <Place>[] routes, int clearance, Style style) { bool[] currentCanStep = new bool[routes.Length]; // on phase 0 cache CanStep for all the 4 phases int[] nextStep = new int[routes.Length]; // step each path forward on phase 3, if it CanStep for (int i = 0; i < nextStep.Length; i++) { nextStep[i] = 1; } bool allFinished; do { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } allFinished = true; for (int phase = 0; phase < 4; phase++) { // DEBUG BREAK HERE: bool stepped = false; for (int r = 0; r < routes.Length; r++) { if (nextStep[r] < routes[r].Count) { allFinished = false; Place current = routes[r][nextStep[r] - 1]; Place next = routes[r][nextStep[r]]; if (phase == 0) { currentCanStep[r] = CanStepTo(current, next, clearance); } if (currentCanStep[r]) { StepPhase(phase, StepDirection(current, next, style), current, next, style); stepped = true; if (phase == 3) { nextStep[r]++; } } } } if (!allFinished && !stepped) { throw new Error("ERROR: FollowRoutes failed"); } KGui.gui.GuiDeviceUpdate(); if (phase < 3) { Thread.Sleep(device.phaseDelay); } else { Thread.Sleep(device.stepDelay); } } } while (!allFinished); }
public void SetAnimation(Animation animation) { lock (KDeviceHandler.device) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } this.animation = animation; } }
// === DEVICE PROTOCOL OPERATIONS === // public void Sample(SampleValue sample, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: NEW DROPLET " + sample.FormatSymbol(style)); Place source = ReservePlaceInColumn(zone["staging"]); placement.Appear(sample, source, style); //placement.Place(sample, source, style); //KGui.gui.GuiDeviceUpdate(); }
public static void PauseEquilibrate(Netlist netlist, Style style) { if (!netlist.autoContinue) { while ((!continueExecution) && Exec.IsExecuting()) { // if (!KGui.gui.GuiContinueEnabled()) KGui.gui.GuiOutputAppendText(netlist.Format(style)); KGui.gui.GuiContinueEnable(true); Thread.Sleep(100); } KGui.gui.GuiContinueEnable(false); continueExecution = false; //KGui.gui.GuiOutputSetText(""); // clear last results in preparation for the next, only if not autoContinue } }
public void Concentrate(List <SampleValue> outSamples, List <SampleValue> inSamples, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: CONCENTRATE " + Style.FormatSequence(outSamples, ", ", x =>x.FormatSymbol(style)) + " = " + Style.FormatSequence(inSamples, ", ", x => x.FormatSymbol(style))); for (int i = 0; i < inSamples.Count; i++) { Place place = placement.PlaceOf(inSamples[i], style); placement.Remove(inSamples[i], style); placement.Place(outSamples[i], place, style); } KGui.gui.GuiDeviceUpdate(); }
public SampleValue Extract(Place place, Style style, bool log = true) { lock (KDeviceHandler.device) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } CheckIsOccupied(place); SampleValue sample = placeToSample[place]; //if (log) Gui.Log("Device: Extract " + sample.FormatSymbol(style) + " from " + place.Format(style)); sampleToPlace.Remove(sample); placeToSample.Remove(place); sampleToStyle.Remove(sample); return(sample); } }
public Place Remove(SampleValue sample, Style style, bool log = true) { lock (KDeviceHandler.device) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } CheckIsPlaced(sample, style); Place place = sampleToPlace[sample]; //if (log) Gui.Log("Device: Remove " + sample.FormatSymbol(style) + " from " + place.Format(style)); sampleToPlace.Remove(sample); placeToSample.Remove(place); sampleToStyle.Remove(sample); return(place); } }
private void StartAction(bool forkWorker, bool autoContinue = false) { guiControls.SplashOff(); if (Exec.IsExecuting() && !ContinueEnabled()) { return; // we are already running a simulation, don't start a concurrent one } if (Exec.IsExecuting() && ContinueEnabled()) // we are already running a simulation; make start button work as continue button { Protocol.continueExecution = true; if (Exec.lastExecution != null) { Exec.lastExecution.netlist.autoContinue = autoContinue; } } else // do a start { Exec.Execute_Starter(forkWorker, autoContinue: autoContinue); // This is where it all happens } }
public void Dispose(List <SampleValue> samples, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: DISPOSE " + Style.FormatSequence(samples, ", ", x => x.FormatSymbol(style))); Place[,] area = FreeAreaInColumn(zone["mixing"], minRow: 0, rows: 1, cols: 2 * samples.Count - 1); // find free columns in "mixing" block, on the same row List <Place>[] routes = new List <Place> [samples.Count]; for (int i = 0; i < samples.Count; i++) { routes[i] = placement.PathHorFirst(placement.PlaceOf(samples[i], style), area[0, 2 * i]); } placement.FollowRoutes(routes, clearance: 1, style); for (int i = 0; i < samples.Count; i++) { placement.Disappear(placement.PlaceOf(samples[i], style), style); } }
public void Place(SampleValue sample, Place place, Style style, bool log = true) { lock (KDeviceHandler.device) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } if (IsPlaced(sample)) { throw new Error("ERROR Device.Placement.Place"); } if (IsOccupied(place)) { throw new Error("ERROR Device.Placement.Place"); } //if (log) Gui.Log("Device: Place " + sample.FormatSymbol(style) + " into " + place.Format(style)); sampleToPlace[sample] = place; placeToSample[place] = sample; sampleToStyle[sample] = style; } }
public void EndEquilibrate(List <Place> goBacks, List <SampleValue> outSamples, List <SampleValue> inSamples, double fortime, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } //Gui.Log("Device: EQUILIBRATE End " + Style.FormatSequence(outSamples, ", ", x => x.FormatSymbol(style)) + " = " + Style.FormatSequence(inSamples, ", ", x => x.FormatSymbol(style)) + " for " + style.FormatDouble(fortime)); device.dropletColor = dropletColorRed; device.dropletBiggieColor = dropletColorPurple; for (int i = 0; i < inSamples.Count; i++) { Place place = placement.PlaceOf(inSamples[i], style); placement.Remove(inSamples[i], style, log: false); placement.Place(outSamples[i], place, style, log: false); } KGui.gui.GuiDeviceUpdate(); List <Place>[] routes = new List <Place> [inSamples.Count]; for (int i = 0; i < inSamples.Count; i++) { routes[i] = placement.PathVerFirst(placement.PlaceOf(outSamples[i], style), goBacks[i]); } placement.FollowRoutes(routes, clearance: 1, style); }
public void Regulate(List <SampleValue> outSamples, List <SampleValue> inSamples, Style style) { if (!Exec.IsExecuting()) { throw new ExecutionEnded(""); } List <Place>[] routes = new List <Place> [inSamples.Count]; //Gui.Log("Device: REGULATE " + Style.FormatSequence(outSamples, ", ", x =>x.FormatSymbol(style)) + " = " + Style.FormatSequence(inSamples, ", ", x => x.FormatSymbol(style))); for (int i = 0; i < inSamples.Count; i++) { string toZone = (outSamples[i].Temperature() < KDeviceHandler.coldTemperature) ? "staging" : (outSamples[i].Temperature() > KDeviceHandler.hotTemperature) ? "hot" : "warm"; Place from = placement.PlaceOf(inSamples[i], style); Place place = FreePlaceInColumn(zone[toZone], minRow: from.Row(), currentlyAt: from, skipNo: 0); routes[i] = placement.PathHorFirst(placement.PlaceOf(inSamples[i], style), place); } placement.FollowRoutes(routes, clearance: 1, style); for (int i = 0; i < inSamples.Count; i++) { Place place = placement.PlaceOf(inSamples[i], style); placement.Remove(inSamples[i], style); placement.Place(outSamples[i], place, style); } KGui.gui.GuiDeviceUpdate(); }
public static bool IsSimulating() { return(Exec.IsExecuting() && !ContinueEnabled()); }
Integrate(Func <double, double, Vector, Func <double, Vector, Vector>, IEnumerable <SolPoint> > Solver, State initialState, double initialTime, double finalTime, Func <double, Vector, Vector> Flux, SampleValue sample, List <ReportEntry> reports, Noise noise, bool nonTrivialSolution, Style style) { double redrawTick = initialTime; double redrawStep = (finalTime - initialTime) / 50; double densityTick = initialTime; double densityStep = (finalTime - initialTime) / 1000; int pointsCounter = 0; int renderedCounter = 0; double lastTime = finalTime; State lastState = null; if (initialState.NaN()) { Gui.Log("Initial state contains NaN."); return(lastTime, lastState); } KChartHandler.ChartClearData(style); (string[] series, string[] seriesLNA) = GenerateSeries(reports, noise, style); KChartHandler.LegendUpdate(style); KScoreHandler.ScoreUpdate(); IEnumerable <SolPoint> solution = SolutionGererator(Solver, initialState, initialTime, finalTime, Flux, nonTrivialSolution, style); List <TriggerEntry> triggers = sample.Triggers(style); bool[] triggered = new bool[triggers.Count]; for (int i = 0; i < triggers.Count; i++) { triggered[i] = false; } // BEGIN foreach (SolPoint solPoint in solution) -- done by hand to catch exceptions in MoveNext() SolPoint solPoint = new SolPoint(initialTime, initialState.Clone().ToArray()); bool hasSolPoint = false; var enumerator = solution.GetEnumerator(); do { // Handle triggers first, they can apply to the initial state if (triggers.Count > 0) { State state = null; // allocated on need from solPoint State modifiedState = null; // allocated on need from state for (int i = 0; i < triggers.Count; i++) { if (triggered[i] == false) { TriggerEntry trigger = triggers[i]; if (state == null) { state = new State(sample.Count(), lna: noise != Noise.None).InitAll(solPoint.X); } if (trigger.condition.ObserveBool(sample, solPoint.T, state, Flux, style)) { if (modifiedState == null) { modifiedState = state.Clone(); } double rawValue = trigger.assignment.ObserveMean(sample, solPoint.T, state, Flux, style); double assignment = trigger.sample.stateMap.NormalizeDimension(trigger.target, rawValue, trigger.dimension, trigger.sample.Volume(), style); int index = sample.stateMap.IndexOf(trigger.target.symbol); modifiedState.SetMean(index, assignment); if (noise != Noise.None && trigger.assignmentVariance != null) { double rawValueVariance = trigger.assignmentVariance.ObserveMean(sample, solPoint.T, state, Flux, style); double assignmentVariance = trigger.sample.stateMap.NormalizeDimension(trigger.target, rawValueVariance, trigger.dimension, trigger.sample.Volume(), style); modifiedState.SetCovar(index, index, assignmentVariance); } triggered[i] = true; } } } if (modifiedState != null) //restart the solver { State newState = modifiedState; // new State(sample.Count(), lna: noise != Noise.None).InitAll(modifiedState.ToArray()); solution = SolutionGererator(Solver, newState, solPoint.T, finalTime, Flux, nonTrivialSolution, style); enumerator = solution.GetEnumerator(); } } try { if (!enumerator.MoveNext()) { break; } solPoint = enumerator.Current; // get next step of integration from solver hasSolPoint = true; } catch (ConstantEvaluation e) { // stop simulation but allow execution to proceed Gui.Log("Simulation stopped and ignored: cannot evaluate constant '" + e.Message + "'"); return(lastTime, lastState); } catch (Error e) { throw new Error(e.Message); } catch (Exception e) { KChartHandler.ChartUpdate(style, false); throw new Error("ODE Solver FAILED: " + e.Message); } pointsCounter++; // LOOP BODY of foreach (SolPoint solPoint in solution): if (!Exec.IsExecuting()) { KChartHandler.ChartUpdate(style); throw new ExecutionEnded(""); } // break; if (style.chartOutput) // Plot the new solution point { if (solPoint.T >= densityTick) // avoid drawing too many points { State state = new State(sample.Count(), lna: noise != Noise.None).InitAll(solPoint.X); for (int i = 0; i < reports.Count; i++) { if (series[i] != null) // if a series was actually generated from this report // generate deterministic series { if ((noise == Noise.None && reports[i].flow.HasDeterministicValue()) || (noise != Noise.None && reports[i].flow.HasStochasticMean())) { double mean = reports[i].flow.ObserveMean(sample, solPoint.T, state, Flux, style); KChartHandler.ChartAddPoint(series[i], solPoint.T, mean, 0.0, Noise.None); } // generate LNA-dependent series if (noise != Noise.None && reports[i].flow.HasStochasticVariance() && !reports[i].flow.HasNullVariance()) { double mean = reports[i].flow.ObserveMean(sample, solPoint.T, state, Flux, style); double variance = reports[i].flow.ObserveVariance(sample, solPoint.T, state, style); KChartHandler.ChartAddPoint(seriesLNA[i], solPoint.T, mean, variance, noise); } } } renderedCounter++; densityTick += densityStep; } if (solPoint.T >= redrawTick) // avoid redrawing the plot too often { KChartHandler.ChartUpdate(style, incremental: true); redrawTick += redrawStep; } } lastTime = solPoint.T; // END foreach (SolPoint solPoint in solution) } while (true); if (hasSolPoint) { lastState = new State(sample.Count(), lna: noise != Noise.None).InitAll(solPoint.X); } KChartHandler.ChartUpdate(style, incremental: false); return(lastTime, lastState); }