/// <summary> /// Set up the simulation. /// </summary> /// <param name="entities">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> /// <exception cref="SpiceSharp.CircuitException"> /// {0}: No time configuration".FormatString(Name) /// or /// {0}: No integration method specified".FormatString(Name) /// </exception> protected override void Setup(EntityCollection entities) { entities.ThrowIfNull(nameof(entities)); base.Setup(entities); // Get behaviors and configurations var config = Configurations.Get <TimeConfiguration>().ThrowIfNull("time configuration"); _useIc = config.UseIc; Method = config.Method.ThrowIfNull("method"); _transientBehaviors = EntityBehaviors.GetBehaviorList <ITimeBehavior>(); _acceptBehaviors = EntityBehaviors.GetBehaviorList <IAcceptBehavior>(); // Allow all transient behaviors to allocate equation elements and create states for (var i = 0; i < _transientBehaviors.Count; i++) { _transientBehaviors[i].GetEquationPointers(RealState.Solver); _transientBehaviors[i].CreateStates(Method); } Method.Setup(this); // Set up initial conditions foreach (var ic in config.InitialConditions) { _initialConditions.Add(new ConvergenceAid(ic.Key, ic.Value)); } }
/// <summary> /// A default implementation for validating entities and behaviors using the specified rules. /// </summary> /// <param name="rules">The rules.</param> /// <param name="entities">The entities.</param> /// <exception cref="ValidationFailedException">Thrown if the validation failed.</exception> protected void Validate(IRules rules, IEntityCollection entities) { if (rules == null) { return; } if (entities != null) { foreach (var entity in entities) { if (entity is IRuleSubject subject) { subject.Apply(rules); } } } foreach (var behavior in EntityBehaviors.SelectMany(p => p)) { if (behavior is IRuleSubject subject) { subject.Apply(rules); } } // Are there still violated rules? if (rules.ViolationCount > 0) { throw new ValidationFailedException(this, rules); } }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="circuit">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> /// <exception cref="SpiceSharp.CircuitException"> /// No frequency configuration found /// or /// No frequency sweep found /// </exception> protected override void Setup(Circuit circuit) { if (circuit == null) { throw new ArgumentNullException(nameof(circuit)); } base.Setup(circuit); // Get behaviors, configurations and states var config = Configurations.Get <FrequencyConfiguration>(); _frequencyBehaviors = EntityBehaviors.GetBehaviorList <IFrequencyBehavior>(); FrequencySweep = config.FrequencySweep ?? throw new CircuitException("No frequency sweep found"); // Create the state for complex numbers ComplexState = new ComplexSimulationState(); _loadStateEventArgs = new LoadStateEventArgs(ComplexState); var strategy = ComplexState.Solver.Strategy; strategy.RelativePivotThreshold = config.RelativePivotThreshold; strategy.AbsolutePivotThreshold = config.AbsolutePivotThreshold; // Setup behaviors var solver = ComplexState.Solver; for (var i = 0; i < _frequencyBehaviors.Count; i++) { _frequencyBehaviors[i].GetEquationPointers(solver); } ComplexState.Setup(Variables); }
/// <inheritdoc/> protected override void CreateBehaviors(IEntityCollection entities) { base.CreateBehaviors(entities); _temperatureBehaviors = EntityBehaviors.GetBehaviorList <ITemperatureBehavior>(); _loadBehaviors = EntityBehaviors.GetBehaviorList <IBiasingBehavior>(); _convergenceBehaviors = EntityBehaviors.GetBehaviorList <IConvergenceBehavior>(); _updateBehaviors = EntityBehaviors.GetBehaviorList <IBiasingUpdateBehavior>(); // We're going to set up our state now that all behaviors have allocated elements in the solver _state.Setup(); // Set up nodesets for nodes that were referenced by an entity _nodesets.Clear(); foreach (var ns in BiasingParameters.Nodesets) { if (_state.TryGetValue(ns.Key, out var variable)) { _nodesets.Add(new ConvergenceAid(variable, _state, ns.Value)); } else { SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_ConvergenceAidVariableNotFound.FormatString(ns.Key)); } } }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="entities">The circuit that will be used.</param> protected override void Setup(EntityCollection entities) { entities.ThrowIfNull(nameof(entities)); // Get behaviors, configurations and states var config = Configurations.Get <FrequencyConfiguration>(); FrequencySweep = config.FrequencySweep.ThrowIfNull("frequency sweep"); // Create the state for complex numbers ComplexState = new ComplexSimulationState(); var strategy = ComplexState.Solver.Strategy; strategy.RelativePivotThreshold = config.RelativePivotThreshold; strategy.AbsolutePivotThreshold = config.AbsolutePivotThreshold; // Setup the rest of the behaviors base.Setup(entities); // Cache local variables _frequencyBehaviors = EntityBehaviors.GetBehaviorList <IFrequencyBehavior>(); _loadStateEventArgs = new LoadStateEventArgs(ComplexState); ComplexState.Setup(Variables); }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="entities">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> /// <exception cref="SpiceSharp.CircuitException"> /// No frequency configuration found /// or /// No frequency sweep found /// </exception> protected override void Setup(EntityCollection entities) { entities.ThrowIfNull(nameof(entities)); base.Setup(entities); // Get behaviors, configurations and states var config = Configurations.Get <FrequencyConfiguration>(); _frequencyBehaviors = EntityBehaviors.GetBehaviorList <IFrequencyBehavior>(); FrequencySweep = config.FrequencySweep.ThrowIfNull("frequency sweep"); // Create the state for complex numbers ComplexState = new ComplexSimulationState(); _loadStateEventArgs = new LoadStateEventArgs(ComplexState); var strategy = ComplexState.Solver.Strategy; strategy.RelativePivotThreshold = config.RelativePivotThreshold; strategy.AbsolutePivotThreshold = config.AbsolutePivotThreshold; // Setup behaviors var solver = ComplexState.Solver; for (var i = 0; i < _frequencyBehaviors.Count; i++) { _frequencyBehaviors[i].GetEquationPointers(solver); } ComplexState.Setup(Variables); }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="entities">The circuit that will be used.</param> protected override void Setup(EntityCollection entities) { entities.ThrowIfNull(nameof(entities)); // Get behaviors and configurations var config = Configurations.Get <TimeConfiguration>().ThrowIfNull("time configuration"); _useIc = config.UseIc; Method = config.Method.ThrowIfNull("method"); // Setup base.Setup(entities); // Cache local variables _transientBehaviors = EntityBehaviors.GetBehaviorList <ITimeBehavior>(); _acceptBehaviors = EntityBehaviors.GetBehaviorList <IAcceptBehavior>(); Method.Setup(this); // Set up initial conditions foreach (var ic in config.InitialConditions) { _initialConditions.Add(new ConvergenceAid(ic.Key, ic.Value)); } }
/// <inheritdoc /> protected override void CreateBehaviors(IEntityCollection entities) { base.CreateBehaviors(entities); _frequencyBehaviors = EntityBehaviors.GetBehaviorList <IFrequencyBehavior>(); _frequencyUpdateBehaviors = EntityBehaviors.GetBehaviorList <IFrequencyUpdateBehavior>(); _state.Setup(); }
/// <summary> /// Destroys the simulation. /// </summary> protected virtual void Unsetup() { // Clear all parameters EntityBehaviors.Clear(); EntityBehaviors = null; EntityParameters.Clear(); EntityParameters = null; // Clear all nodes Variables.Clear(); Variables = null; }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="circuit">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> protected override void Setup(Circuit circuit) { if (circuit == null) { throw new ArgumentNullException(nameof(circuit)); } base.Setup(circuit); // Get behaviors and configuration data var config = Configurations.Get <BaseConfiguration>(); DcMaxIterations = config.DcMaxIterations; AbsTol = config.AbsoluteTolerance; RelTol = config.RelativeTolerance; _temperatureBehaviors = EntityBehaviors.GetBehaviorList <ITemperatureBehavior>(); _loadBehaviors = EntityBehaviors.GetBehaviorList <IBiasingBehavior>(); _initialConditionBehaviors = EntityBehaviors.GetBehaviorList <IInitialConditionBehavior>(); // Create the state for this simulation RealState = new BaseSimulationState { Gmin = config.Gmin }; _isPreordered = false; _shouldReorder = true; var strategy = RealState.Solver.Strategy; strategy.RelativePivotThreshold = config.RelativePivotThreshold; strategy.AbsolutePivotThreshold = config.AbsolutePivotThreshold; // Setup the load behaviors _realStateLoadArgs = new LoadStateEventArgs(RealState); for (var i = 0; i < _loadBehaviors.Count; i++) { _loadBehaviors[i].GetEquationPointers(Variables, RealState.Solver); } RealState.Setup(Variables); // TODO: Compatibility - nodesets from nodes instead of configuration should be removed eventually if (config.Nodesets.Count == 0) { foreach (var ns in Variables.NodeSets) { _nodesets.Add(new ConvergenceAid(ns.Key, ns.Value)); } } // Set up nodesets foreach (var ns in config.Nodesets) { _nodesets.Add(new ConvergenceAid(ns.Key, ns.Value)); } }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="entities">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> protected override void Setup(EntityCollection entities) { entities.ThrowIfNull(nameof(entities)); base.Setup(entities); // Get behaviors _noiseBehaviors = EntityBehaviors.GetBehaviorList <INoiseBehavior>(); // Get behaviors, parameters and states NoiseConfiguration = Configurations.Get <NoiseConfiguration>(); NoiseState = new NoiseState(); NoiseState.Setup(Variables); }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="circuit">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> protected override void Setup(Circuit circuit) { if (circuit == null) { throw new ArgumentNullException(nameof(circuit)); } base.Setup(circuit); // Get behaviors _noiseBehaviors = EntityBehaviors.GetBehaviorList <INoiseBehavior>(); // Get behaviors, parameters and states NoiseConfiguration = Configurations.Get <NoiseConfiguration>(); NoiseState = new NoiseState(); NoiseState.Setup(Variables); }
/// <summary> /// Collect behaviors of all circuit entities while also setting them up /// </summary> /// <typeparam name="T">Base behavior</typeparam> /// <returns></returns> protected BehaviorList <T> SetupBehaviors <T>(IEnumerable <Entity> entities) where T : Behavior { if (entities == null) { throw new ArgumentNullException(nameof(entities)); } // Register all behaviors foreach (var o in entities) { T behavior = o.CreateBehavior <T>(this); if (behavior != null) { EntityBehaviors.Add(o.Name, behavior); } } return(EntityBehaviors.GetBehaviorList <T>()); }
/// <summary> /// Set up all behaviors previously created. /// </summary> /// <param name="entities">The circuit entities.</param> private void SetupBehaviors(IEnumerable <Entity> entities) { var behaviors = new HashSet <IBehavior>(); foreach (var entity in entities) { behaviors.Clear(); // Create the behaviors in the reverse order to allow inheritance for (var i = BehaviorTypes.Count - 1; i >= 0; i--) { IBehavior behavior = null; var type = BehaviorTypes[i]; // Try to reuse a behavior first if (EntityBehaviors.TryGetBehaviors(entity.Name, out var ebd)) { // If the entity behaviors already contains the type, reuse that object ebd.TryGetValue(type, out behavior); } // If it doesn't exist, request a new behavior if (behavior == null) { behavior = entity.CreateBehavior(type, this); } // Add the behavior to the pool if (behavior != null) { EntityBehaviors.Add(type, entity.Name, behavior); behaviors.Add(behavior); } } // Setup the distinct behaviors foreach (var behavior in behaviors) { entity.SetupBehavior(behavior, this); } } }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="circuit">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> protected override void Setup(EntityCollection circuit) { circuit.ThrowIfNull(nameof(circuit)); base.Setup(circuit); // Get behaviors and configuration data var config = Configurations.Get <BaseConfiguration>().ThrowIfNull("base configuration"); DcMaxIterations = config.DcMaxIterations; AbsTol = config.AbsoluteTolerance; RelTol = config.RelativeTolerance; _temperatureBehaviors = EntityBehaviors.GetBehaviorList <ITemperatureBehavior>(); _loadBehaviors = EntityBehaviors.GetBehaviorList <IBiasingBehavior>(); _initialConditionBehaviors = EntityBehaviors.GetBehaviorList <IInitialConditionBehavior>(); // Create the state for this simulation RealState = new BaseSimulationState { Gmin = config.Gmin }; _isPreordered = false; _shouldReorder = true; var strategy = RealState.Solver.Strategy; strategy.RelativePivotThreshold = config.RelativePivotThreshold; strategy.AbsolutePivotThreshold = config.AbsolutePivotThreshold; // Setup the load behaviors _realStateLoadArgs = new LoadStateEventArgs(RealState); for (var i = 0; i < _loadBehaviors.Count; i++) { _loadBehaviors[i].GetEquationPointers(Variables, RealState.Solver); } RealState.Setup(Variables); // Set up nodesets foreach (var ns in config.Nodesets) { _nodesets.Add(new ConvergenceAid(ns.Key, ns.Value)); } }
/// <summary> /// Set up the simulation. /// </summary> /// <param name="circuit">The circuit that will be used.</param> /// <exception cref="ArgumentNullException">circuit</exception> /// <exception cref="SpiceSharp.CircuitException"> /// {0}: No time configuration".FormatString(Name) /// or /// {0}: No integration method specified".FormatString(Name) /// </exception> protected override void Setup(Circuit circuit) { if (circuit == null) { throw new ArgumentNullException(nameof(circuit)); } base.Setup(circuit); // Get behaviors and configurations var config = Configurations.Get <TimeConfiguration>() ?? throw new CircuitException("{0}: No time configuration".FormatString(Name)); _useIc = config.UseIc; Method = config.Method ?? throw new CircuitException("{0}: No integration method specified".FormatString(Name)); _transientBehaviors = EntityBehaviors.GetBehaviorList <ITimeBehavior>(); _acceptBehaviors = EntityBehaviors.GetBehaviorList <IAcceptBehavior>(); // Allow all transient behaviors to allocate equation elements and create states for (var i = 0; i < _transientBehaviors.Count; i++) { _transientBehaviors[i].GetEquationPointers(RealState.Solver); _transientBehaviors[i].CreateStates(Method); } Method.Setup(this); // TODO: Compatibility - initial conditions from nodes instead of configuration should be removed eventually if (config.InitialConditions.Count == 0) { foreach (var ns in Variables.InitialConditions) { _initialConditions.Add(new ConvergenceAid(ns.Key, ns.Value)); } } // Set up initial conditions foreach (var ic in config.InitialConditions) { _initialConditions.Add(new ConvergenceAid(ic.Key, ic.Value)); } }
/// <inheritdoc/> protected override void CreateBehaviors(IEntityCollection entities) { base.CreateBehaviors(entities); _transientBehaviors = EntityBehaviors.GetBehaviorList <ITimeBehavior>(); _acceptBehaviors = EntityBehaviors.GetBehaviorList <IAcceptBehavior>(); _truncatingBehaviors = EntityBehaviors.GetBehaviorList <ITruncatingBehavior>(); _method.Initialize(); // Set up initial conditions var state = GetState <IBiasingSimulationState>(); _initialConditions.Clear(); foreach (var ic in TimeParameters.InitialConditions) { if (state.ContainsKey(ic.Key)) { _initialConditions.Add(new ConvergenceAid(state.GetSharedVariable(ic.Key), GetState <IBiasingSimulationState>(), ic.Value)); } else { SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_ConvergenceAidVariableNotFound.FormatString(ic.Key)); } } }
/// <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]); } }
/// <inheritdoc /> protected override void CreateBehaviors(IEntityCollection entities) { base.CreateBehaviors(entities); _noiseBehaviors = EntityBehaviors.GetBehaviorList <INoiseBehavior>(); }