/// <inheritdoc/> protected override void Execute() { base.Execute(); Op(BiasingParameters.DcMaxIterations); var exportargs = new ExportDataEventArgs(this); OnExport(exportargs); }
/// <summary> /// Executes the simulation. /// </summary> protected override void Execute() { base.Execute(); var state = RealState; var cstate = ComplexState; var nstate = NoiseState; var noiseconfig = NoiseConfiguration; var exportargs = new ExportDataEventArgs(this); // Find the output nodes var posOutNode = noiseconfig.Output != null?Variables.GetNode(noiseconfig.Output).Index : 0; var negOutNode = noiseconfig.OutputRef != null?Variables.GetNode(noiseconfig.OutputRef).Index : 0; // Initialize nstate.Reset(FrequencySweep.Initial); cstate.Laplace = 0; state.UseIc = false; state.UseDc = true; Op(DcMaxIterations); // Load all in order to calculate the AC info for all devices InitializeAcParameters(); // Connect noise sources for (var i = 0; i < _noiseBehaviors.Count; i++) { _noiseBehaviors[i].ConnectNoise(); } // Loop through noise figures foreach (var freq in FrequencySweep.Points) { nstate.Frequency = freq; cstate.Laplace = new Complex(0.0, 2.0 * Math.PI * freq); AcIterate(); var val = cstate.Solution[posOutNode] - cstate.Solution[negOutNode]; nstate.GainInverseSquared = 1.0 / Math.Max(val.Real * val.Real + val.Imaginary * val.Imaginary, 1e-20); // Solve the adjoint system NzIterate(posOutNode, negOutNode); // Now we use the adjoint system to calculate the noise // contributions of each generator in the circuit nstate.OutputNoiseDensity = 0.0; for (var i = 0; i < _noiseBehaviors.Count; i++) { _noiseBehaviors[i].Noise(); } // Export the data OnExport(exportargs); } }
/// <inheritdoc/> protected override void Execute() { base.Execute(); var cstate = (ComplexSimulationState)GetState <IComplexSimulationState>(); var noiseconfig = NoiseParameters; var exportargs = new ExportDataEventArgs(this); // Find the output nodes var posOutNode = noiseconfig.Output != null ? cstate.Map[cstate.GetSharedVariable(noiseconfig.Output)] : 0; var negOutNode = noiseconfig.OutputRef != null ? cstate.Map[cstate.GetSharedVariable(noiseconfig.OutputRef)] : 0; // Initialize var freq = FrequencyParameters.Frequencies.GetEnumerator(); if (!freq.MoveNext()) { return; } cstate.Laplace = 0; Op(BiasingParameters.DcMaxIterations); // Initialize all devices for small-signal analysis and reset all noise contributions InitializeAcParameters(); foreach (var behavior in _noiseBehaviors) { behavior.Initialize(); } // Loop through noise figures do { // First compute the AC gain cstate.Laplace = new Complex(0.0, 2.0 * Math.PI * freq.Current); AcIterate(); var val = cstate.Solution[posOutNode] - cstate.Solution[negOutNode]; var inverseGainSquared = 1.0 / Math.Max(val.Real * val.Real + val.Imaginary * val.Imaginary, 1e-20); _state.SetCurrentPoint(new NoisePoint(freq.Current, inverseGainSquared)); // Solve the adjoint system NzIterate(posOutNode, negOutNode); // Now we use the adjoint system to calculate the noise // contributions of each generator in the circuit foreach (var behavior in _noiseBehaviors) { behavior.Compute(); _state.Add(behavior); } // Export the data OnExport(exportargs); }while (freq.MoveNext()); }
/// <summary> /// Executes the simulation. /// </summary> protected override void Execute() { // Execute base behavior base.Execute(); var state = RealState; var cstate = ComplexState; // Calculate the operating point cstate.Laplace = 0.0; state.UseIc = false; state.UseDc = true; Op(DcMaxIterations); // Load all in order to calculate the AC info for all devices FrequencySimulationStatistics.ComplexTime.Start(); try { InitializeAcParameters(); // Export operating point if requested var exportargs = new ExportDataEventArgs(this); if (_keepOpInfo) { OnExport(exportargs); } // Sweep the frequency foreach (var freq in FrequencySweep.Points) { // Calculate the current frequency cstate.Laplace = new Complex(0.0, 2.0 * Math.PI * freq); // Solve AcIterate(); // Export the timepoint OnExport(exportargs); } FrequencySimulationStatistics.ComplexTime.Stop(); } catch (Exception) { FrequencySimulationStatistics.ComplexTime.Stop(); throw; } }
/// <summary> /// Executes the simulation. /// </summary> protected override void Execute() { base.Execute(); // Setup the state var state = RealState; state.UseIc = false; // UseIC is only used in transient simulations state.UseDc = true; Op(DcMaxIterations); var exportargs = new ExportDataEventArgs(this); OnExport(exportargs); }
/// <summary> /// Execute /// </summary> protected override void Execute() { // Execute base behavior base.Execute(); var state = RealState; var cstate = ComplexState; var baseconfig = BaseConfiguration; var freqconfig = FrequencyConfiguration; // Calculate the operating point cstate.Laplace = 0.0; state.Domain = RealState.DomainType.Frequency; state.Gmin = baseconfig.Gmin; Op(baseconfig.DcMaxIterations); // Load all in order to calculate the AC info for all devices for (int i = 0; i < LoadBehaviors.Count; i++) { LoadBehaviors[i].Load(this); } for (int i = 0; i < FrequencyBehaviors.Count; i++) { FrequencyBehaviors[i].InitializeParameters(this); } // Export operating point if requested var exportargs = new ExportDataEventArgs(this); if (freqconfig.KeepOpInfo) { Export(exportargs); } // Sweep the frequency foreach (double freq in FrequencySweep.Points) { // Calculate the current frequency cstate.Laplace = new Complex(0.0, 2.0 * Math.PI * freq); // Solve AcIterate(); // Export the timepoint Export(exportargs); } }
/// <summary> /// Executes the simulation. /// </summary> /// <exception cref="SpiceSharp.CircuitException">{0}: transient terminated".FormatString(Name)</exception> protected override void Execute() { // First do temperature-dependent calculations and IC base.Execute(); exportargs = new ExportDataEventArgs(this); timeConfig = Configurations.Get <TimeConfiguration>(); // Start our statistics Statistics.TransientTime.Start(); startIters = Statistics.Iterations; startselapsed = Statistics.SolveTime.Elapsed; simulationRunning = true; if (!StepByStepSimulation) { DoTick(); } }
/// <inheritdoc/> protected override void Execute() { // Execute base behavior base.Execute(); var cstate = (ComplexSimulationState)GetState <IComplexSimulationState>(); // Calculate the operating point cstate.Laplace = 0.0; Op(BiasingParameters.DcMaxIterations); // Load all in order to calculate the AC info for all devices Statistics.ComplexTime.Start(); try { InitializeAcParameters(); // Export operating point if requested var exportargs = new ExportDataEventArgs(this); if (FrequencyParameters.KeepOpInfo) { OnExport(exportargs); } // Sweep the frequency foreach (var freq in FrequencyParameters.Frequencies) { // Calculate the current frequency cstate.Laplace = new Complex(0.0, 2.0 * Math.PI * freq); // Solve AcIterate(); // Export the timepoint OnExport(exportargs); } } finally { Statistics.ComplexTime.Stop(); } }
/// <inheritdoc/> protected override void Execute() { base.Execute(); // Calculate the operating point of the circuit _time.UseIc = TimeParameters.UseIc; _time.UseDc = true; if (_time.UseIc) { // Copy initial conditions in the current solution such that device may be able to copy them // in InitializeStates() var state = GetState <IBiasingSimulationState>(); foreach (var ic in _initialConditions) { var index = state.Map[ic.Variable]; state.Solution[index] = ic.Value; state.OldSolution[index] = ic.Value; // Just to make sure... } } else { if (_initialConditions.Count > 0) { AfterLoad += LoadInitialConditions; Op(BiasingParameters.DcMaxIterations); AfterLoad -= LoadInitialConditions; } else { Op(BiasingParameters.DcMaxIterations); } } Statistics.TimePoints++; // Stop calculating the operating point and allow the devices to // retrieve their initial conditions if necessary InitializeStates(); _time.UseIc = false; _time.UseDc = false; var exportargs = new ExportDataEventArgs(this); // Start our statistics var stats = ((BiasingSimulation)this).Statistics; var startIters = stats.Iterations; var startselapsed = stats.SolveTime.Elapsed; Statistics.TransientTime.Start(); try { while (true) { // Accept the last evaluated time point Accept(); // Export the current timepoint if (_method.Time >= TimeParameters.StartTime) { OnExport(exportargs); } // Detect the end of the simulation if (_method.Time >= TimeParameters.StopTime) { // Keep our statistics Statistics.TransientTime.Stop(); Statistics.TransientIterations += stats.Iterations - startIters; Statistics.TransientSolveTime += stats.SolveTime.Elapsed - startselapsed; // Finished! return; } // Continue integration foreach (var behavior in _truncatingBehaviors) { _method.Truncate(behavior.Prepare()); } _method.Prepare(); // Find a valid time point while (true) { // Probe the next time point Probe(); // Try to solve the new point var converged = TimeIterate(TimeParameters.TransientMaxIterations); Statistics.TimePoints++; // Did we fail to converge to a solution? if (!converged) { _method.Reject(); Statistics.Rejected++; } else { // If our integration method approves of our solution, continue to the next timepoint var max = double.PositiveInfinity; foreach (var behavior in _truncatingBehaviors) { max = Math.Min(behavior.Evaluate(), max); } if (_method.Evaluate(max)) { break; } Statistics.Rejected++; } } } } catch (SpiceSharpException ex) { throw new SpiceSharpException(Properties.Resources.Simulations_Time_Terminated.FormatString(Name), ex); } finally { Statistics.TransientTime.Stop(); Statistics.TransientIterations += stats.Iterations - startIters; Statistics.TransientSolveTime += stats.SolveTime.Elapsed - startselapsed; } }
/// <summary> /// Executes the simulation. /// </summary> /// <exception cref="SpiceSharp.CircuitException"> /// Could not find source {0}".FormatString(sweep.Parameter) /// or /// Invalid sweep object /// </exception> protected override void Execute() { // Base base.Execute(); var exportargs = new ExportDataEventArgs(this); // Setup the state var state = RealState; var dcconfig = Configurations.Get <DCConfiguration>().ThrowIfNull("dc configuration"); state.Init = InitializationModes.Junction; state.UseIc = false; // UseIC is only used in transient simulations state.UseDc = true; // Initialize Sweeps = new NestedSweeps(dcconfig.Sweeps); var swept = new Parameter <double> [Sweeps.Count]; var original = new Parameter <double> [Sweeps.Count]; var levelNeedsTemperature = -1; // Initialize first time for (var i = 0; i < dcconfig.Sweeps.Count; i++) { // Get the component to be swept var sweep = Sweeps[i]; // Try finding the parameter to sweep var args = new DCParameterSearchEventArgs(sweep.Parameter, i); OnParameterSearch?.Invoke(this, args); if (args.Result != null) { swept[i] = args.Result; // Keep track of the highest level that needs to recalculate temperature if (args.TemperatureNeeded) { levelNeedsTemperature = Math.Max(levelNeedsTemperature, i); } } else { // Get entity parameters if (!EntityBehaviors.ContainsKey(sweep.Parameter)) { throw new CircuitException("Could not find source {0}".FormatString(sweep.Parameter)); } var eb = EntityParameters[sweep.Parameter]; // Check for a Voltage source or Current source parameters if (eb.TryGet <Components.CommonBehaviors.IndependentSourceParameters>(out var ibp)) { swept[i] = ibp.DcValue; } else { throw new CircuitException("Invalid sweep object"); } } original[i] = (Parameter <double>)swept[i].Clone(); swept[i].Value = sweep.Initial; } // Execute temperature behaviors if necessary the first time if (levelNeedsTemperature >= 0) { Temperature(); } // Execute the sweeps var level = Sweeps.Count - 1; while (level >= 0) { // Fill the values with start values while (level < Sweeps.Count - 1) { level++; Sweeps[level].Reset(); swept[level].Value = Sweeps[level].CurrentValue; state.Init = InitializationModes.Junction; } // Calculate the solution if (!Iterate(dcconfig.SweepMaxIterations)) { IterationFailed?.Invoke(this, EventArgs.Empty); Op(DcMaxIterations); } // Export data OnExport(exportargs); // Remove all values that are greater or equal to the maximum value while (level >= 0 && Sweeps[level].CurrentStep >= Sweeps[level].Limit) { level--; } // Go to the next step for the top level if (level >= 0) { Sweeps[level].Increment(); swept[level].Value = Sweeps[level].CurrentValue; // If temperature behavior is needed for this level or higher, run behaviors if (levelNeedsTemperature >= level) { Temperature(); } } } // Restore all the parameters of the swept components for (var i = 0; i < Sweeps.Count; i++) { swept[i].CopyFrom(original[i]); } }
/// <summary> /// Raises the <see cref="E:ExportSimulationData" /> event. /// </summary> /// <param name="args">The <see cref="ExportDataEventArgs"/> instance containing the event data.</param> protected virtual void OnExport(ExportDataEventArgs args) => ExportSimulationData?.Invoke(this, args);
/// <inheritdoc/> protected override void Execute() { base.Execute(); var cstate = (ComplexSimulationState)GetState <IComplexSimulationState>(); var noiseconfig = NoiseParameters; var exportargs = new ExportDataEventArgs(this); // Find the output nodes var posOutNode = noiseconfig.Output != null ? cstate.Map[cstate.GetSharedVariable(noiseconfig.Output)] : 0; var negOutNode = noiseconfig.OutputRef != null ? cstate.Map[cstate.GetSharedVariable(noiseconfig.OutputRef)] : 0; // We only want to enable the source that is flagged as the input var source = EntityBehaviors[NoiseParameters.InputSource]; var originalParameters = new List <Tuple <IndependentSourceParameters, double, double> >(); foreach (var container in EntityBehaviors) { if (container.TryGetParameterSet(out IndependentSourceParameters parameters)) { originalParameters.Add(Tuple.Create(parameters, parameters.AcMagnitude, parameters.AcPhase)); if (ReferenceEquals(container, source)) { parameters.AcMagnitude = 1.0; parameters.AcPhase = 0.0; } else { parameters.AcMagnitude = 0.0; parameters.AcPhase = 0.0; } } } try { // Initialize var freq = FrequencyParameters.Frequencies.GetEnumerator(); if (!freq.MoveNext()) { return; } cstate.Laplace = 0; Op(BiasingParameters.DcMaxIterations); // Initialize all devices for small-signal analysis and reset all noise contributions InitializeAcParameters(); foreach (var behavior in _noiseBehaviors) { behavior.Initialize(); } // Loop through noise figures do { // First compute the AC gain cstate.Laplace = new Complex(0.0, 2.0 * Math.PI * freq.Current); AcIterate(); var val = cstate.Solution[posOutNode] - cstate.Solution[negOutNode]; var inverseGainSquared = 1.0 / Math.Max(val.Real * val.Real + val.Imaginary * val.Imaginary, 1e-20); _state.SetCurrentPoint(new NoisePoint(freq.Current, inverseGainSquared)); // Solve the adjoint system NzIterate(posOutNode, negOutNode); // Now we use the adjoint system to calculate the noise // contributions of each generator in the circuit foreach (var behavior in _noiseBehaviors) { behavior.Compute(); _state.Add(behavior); } // Export the data OnExport(exportargs); }while (freq.MoveNext()); } finally { foreach (var parameters in originalParameters) { parameters.Item1.AcMagnitude = parameters.Item2; parameters.Item1.AcPhase = parameters.Item3; } } }
/// <summary> /// Executes the simulation. /// </summary> /// <exception cref="SpiceSharp.CircuitException">{0}: transient terminated".FormatString(Name)</exception> protected override void Execute() { // First do temperature-dependent calculations and IC base.Execute(); var exportargs = new ExportDataEventArgs(this); var timeConfig = Configurations.Get <TimeConfiguration>(); // Start our statistics Statistics.TransientTime.Start(); var startIters = Statistics.Iterations; var startselapsed = Statistics.SolveTime.Elapsed; try { var newDelta = Math.Min(timeConfig.FinalTime / 50.0, timeConfig.Step) / 10.0; while (true) { // Accept the last evaluated time point Accept(); // Export the current timepoint if (Method.Time >= timeConfig.InitTime) { OnExport(exportargs); } // Detect the end of the simulation if (Method.Time >= timeConfig.FinalTime) { // Keep our statistics Statistics.TransientTime.Stop(); Statistics.TransientIterations += Statistics.Iterations - startIters; Statistics.TransientSolveTime += Statistics.SolveTime.Elapsed - startselapsed; // Finished! return; } // Continue integration Method.Continue(this, ref newDelta); // Find a valid time point while (true) { // Probe the next time point Probe(newDelta); // Try to solve the new point var converged = TimeIterate(timeConfig.TranMaxIterations); Statistics.TimePoints++; // Did we fail to converge to a solution? if (!converged) { Method.NonConvergence(this, out newDelta); Statistics.Rejected++; } else { // If our integration method approves of our solution, continue to the next timepoint if (Method.Evaluate(this, out newDelta)) { break; } Statistics.Rejected++; } } } } catch (CircuitException ex) { // Keep our statistics Statistics.TransientTime.Stop(); Statistics.TransientIterations += Statistics.Iterations - startIters; Statistics.TransientSolveTime += Statistics.SolveTime.Elapsed - startselapsed; throw new CircuitException("{0}: transient terminated".FormatString(Name), ex); } }
/// <summary> /// Execute the transient simulation /// </summary> protected override void Execute() { // First do temperature-dependent calculations and IC base.Execute(); var exportargs = new ExportDataEventArgs(this); var state = RealState; var baseConfig = BaseConfiguration; var timeConfig = TimeConfiguration; double delta = Math.Min(timeConfig.FinalTime / 50.0, timeConfig.Step) / 10.0; // Initialize before starting the simulation state.UseIc = timeConfig.UseIc; state.Domain = RealState.DomainType.Time; state.Gmin = baseConfig.Gmin; // Use node initial conditions if device initial conditions are not used if (!timeConfig.UseIc) { OnLoad += LoadInitialConditions; } // Calculate the operating point Op(baseConfig.DcMaxIterations); Statistics.TimePoints++; Method.DeltaOld.Clear(timeConfig.MaxStep); Method.Delta = delta; Method.SaveDelta = timeConfig.FinalTime / 50.0; // Stop calculating a DC solution state.UseIc = false; state.UseDc = false; for (int i = 0; i < TransientBehaviors.Count; i++) { TransientBehaviors[i].GetDcState(this); } StatePool.ClearDc(); OnLoad -= LoadInitialConditions; // Start our statistics Statistics.TransientTime.Start(); int startIters = Statistics.Iterations; var startselapsed = Statistics.SolveTime.Elapsed; try { while (true) { // nextTime: // Accept the current timepoint (CKTaccept()) for (int i = 0; i < AcceptBehaviors.Count; i++) { AcceptBehaviors[i].Accept(this); } Method.SaveSolution(state.Solution); // end of CKTaccept() // Check if current breakpoint is outdated; if so, clear Method.UpdateBreakpoints(); Statistics.Accepted++; // Export the current timepoint if (Method.Time >= timeConfig.InitTime) { Export(exportargs); } // Detect the end of the simulation if (Method.Time >= timeConfig.FinalTime) { // Keep our statistics Statistics.TransientTime.Stop(); Statistics.TransientIterations += Statistics.Iterations - startIters; Statistics.TransientSolveTime += Statistics.SolveTime.Elapsed - startselapsed; // Finished! OnLoad -= LoadInitialConditions; return; } // Pause test - pausing not supported // resume: Method.Delta = Math.Min(Method.Delta, timeConfig.MaxStep); Method.Resume(); StatePool.History.Cycle(); // Calculate a new solution while (true) { Method.TryDelta(); // Compute coefficients and predict a solution and reset states to our previous solution Method.ComputeCoefficients(this); Method.Predict(this); // Try to solve the new point if (Method.SavedTime.Equals(0.0)) { state.Init = RealState.InitializationStates.InitTransient; } bool converged = TimeIterate(timeConfig.TranMaxIterations); Statistics.TimePoints++; // Spice copies the states the first time, we're not // I believe this is because Spice treats the first timepoint after the OP as special (MODEINITTRAN) // We don't treat it special (we just assume it started from a circuit in rest) if (!converged) { // Failed to converge, let's try again with a smaller timestep Method.Rollback(); Statistics.Rejected++; Method.Delta /= 8.0; Method.CutOrder(); var data = new TimestepCutEventArgs(Method.Delta / 8.0, TimestepCutEventArgs.TimestepCutReason.Convergence); TimestepCut?.Invoke(this, data); } else { // Do not check the first time point if (Method.SavedTime.Equals(0.0) || Method.LteControl(this)) { // goto nextTime; break; } Statistics.Rejected++; var data = new TimestepCutEventArgs(Method.Delta, TimestepCutEventArgs.TimestepCutReason.Truncation); TimestepCut?.Invoke(this, data); } if (Method.Delta <= timeConfig.DeltaMin) { if (Method.OldDelta > timeConfig.DeltaMin) { Method.Delta = timeConfig.DeltaMin; } else { throw new CircuitException("Timestep too small at t={0:e}: {1:e}".FormatString(Method.SavedTime, Method.Delta)); } } } } } catch (CircuitException ex) { // Keep our statistics Statistics.TransientTime.Stop(); Statistics.TransientIterations += Statistics.Iterations - startIters; Statistics.TransientSolveTime += Statistics.SolveTime.Elapsed - startselapsed; throw new CircuitException("{0}: transient terminated".FormatString(Name), ex); } }
/// <inheritdoc/> protected override void Execute() { // Base base.Execute(); var exportargs = new ExportDataEventArgs(this); // Setup the state Iteration.Mode = IterationModes.Junction; // Initialize var sweeps = DCParameters.Sweeps.ToArray(); _sweepEnumerators = new IEnumerator <double> [DCParameters.Sweeps.Count]; for (var i = 0; i < sweeps.Length; i++) { _sweepEnumerators[i] = sweeps[i].CreatePoints(this); if (!_sweepEnumerators[i].MoveNext()) { throw new SpiceSharpException(Properties.Resources.Simulations_DC_NoSweepPoints.FormatString(sweeps[i].Name)); } } // Execute the sweeps var level = sweeps.Length - 1; while (level >= 0) { // Fill the values up again by resetting while (level < sweeps.Length - 1) { level++; _sweepEnumerators[level] = sweeps[level].CreatePoints(this); if (!_sweepEnumerators[level].MoveNext()) { throw new SpiceSharpException(Properties.Resources.Simulations_DC_NoSweepPoints.FormatString(sweeps[level].Name)); } Iteration.Mode = IterationModes.Junction; } // Calculate the solution if (!Iterate(DCParameters.SweepMaxIterations)) { IterationFailed?.Invoke(this, EventArgs.Empty); Op(BiasingParameters.DcMaxIterations); } // Export data OnExport(exportargs); // Remove all values that are greater or equal to the maximum value while (level >= 0 && !_sweepEnumerators[level].MoveNext()) { level--; } if (level < 0) { break; } } }
/// <summary> /// Export the data /// </summary> protected void Export(ExportDataEventArgs args) { OnExportSimulationData?.Invoke(this, args); }