From 3825c0c8a3b01bea683fc64fe1716fda913f3ede Mon Sep 17 00:00:00 2001 From: Marcin Date: Sun, 21 Jul 2019 21:40:07 +0200 Subject: [PATCH 1/6] Refactor + bug fixes --- .../Stochastic/DevLotTests.cs | 16 ++ .../Parsers/SpiceExpressionTests.cs | 36 ++++ .../Exporters/CurrentExports/CurrentExport.cs | 4 +- .../CurrentExports/CurrentImaginaryExport.cs | 16 +- .../VoltageExports/VoltageDecibelExport.cs | 6 +- .../CircuitTemperatureSimulationDecorator.cs | 13 +- ...SimulationWithStochasticModelsDecorator.cs | 135 -------------- ...ableStochasticModelsSimulationDecorator.cs | 134 +++++++++++++ .../NominalTemperatureSimulationDecorator.cs | 13 +- ...llParameterSweepsAndTemperaturesFactory.cs | 26 ++- ...ateSimulationsForAllTemperaturesFactory.cs | 8 +- .../CreateSimulationsForMonteCarloFactory.cs | 75 ++++---- ...ateSimulationsForAllTemperaturesFactory.cs | 2 +- .../ICreateSimulationsForMonteCarloFactory.cs | 2 +- .../Simulations/ISimulationDecorator.cs | 9 + .../Simulations/ISimulationsFactory.cs | 12 ++ .../Controls/Simulations/SimulationControl.cs | 61 +----- .../Simulations/SimulationsFactory.cs | 71 +++++++ .../Expression/SpiceExpressionParser.cs | 176 +++++++++++------- 19 files changed, 488 insertions(+), 327 deletions(-) delete mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CreateSimulationWithStochasticModelsDecorator.cs create mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs create mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationDecorator.cs create mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationsFactory.cs create mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationsFactory.cs diff --git a/src/SpiceSharpParser.IntegrationTests/Stochastic/DevLotTests.cs b/src/SpiceSharpParser.IntegrationTests/Stochastic/DevLotTests.cs index 5f85bf4d..52e78bc7 100644 --- a/src/SpiceSharpParser.IntegrationTests/Stochastic/DevLotTests.cs +++ b/src/SpiceSharpParser.IntegrationTests/Stochastic/DevLotTests.cs @@ -27,5 +27,21 @@ public void DevLotMultipleComponentsSameModel() Assert.NotEqual(exports[3], exports[5]); Assert.NotEqual(exports[4], exports[5]); } + + [Fact] + public void When_Mc_Expect_NoException() + { + var result = ParseNetlist( + "Monte Carlo Analysis - DevLot - Diodes", + "D1 OUT 0 1N914", + "V1 OUT 0 0", + ".model 1N914 D(Is=2.52e-9 LOT 10% Rs=0.568 DEV 20%)", + ".OP", + ".LET is {@1N914#D1[Is]}", + ".MC 1000 OP is MAX", + ".END"); + + RunSimulationsAndReturnExports(result); + } } } diff --git a/src/SpiceSharpParser.Tests/Parsers/SpiceExpressionTests.cs b/src/SpiceSharpParser.Tests/Parsers/SpiceExpressionTests.cs index a21e7f07..e202220f 100644 --- a/src/SpiceSharpParser.Tests/Parsers/SpiceExpressionTests.cs +++ b/src/SpiceSharpParser.Tests/Parsers/SpiceExpressionTests.cs @@ -2,12 +2,32 @@ using SpiceSharpParser.ModelReaders.Netlist.Spice.Evaluation; using SpiceSharpParser.Parsers.Expression; using System; +using System.Collections.Generic; using Xunit; namespace SpiceSharpParser.Tests.Parsers { public class SpiceExpressionTests { + public class CustomFunction : IFunction + { + public CustomFunction() + { + ArgumentsCount = 2; + } + + public double Logic(string image, string[] args, IEvaluator evaluator, ExpressionContext context) + { + return 0; + } + + public int ArgumentsCount { get; set; } + public bool Infix { get; set; } + public string Name { get; set; } + public Type ArgumentType => typeof(string); + public Type OutputType { get; } + } + [Fact] public void When_ExpressionHasUnknownParameter_Expect_Exception() { @@ -18,6 +38,21 @@ public void When_ExpressionHasUnknownParameter_Expect_Exception() Assert.Throws(() => parser.Parse("x + 1", new ExpressionParserContext()).Value(new ExpressionEvaluationContext() { ExpressionContext = new ExpressionContext() })); } + [Fact] + public void When_ExpressionHasStringFunctionWithParameters_Expect_Exception() + { + // arrange + var parser = new SpiceExpressionParser(); + + var context = new ExpressionEvaluationContext() {ExpressionContext = new ExpressionContext()}; + context.ExpressionContext.AddFunction("v", new CustomFunction()); + var parserContext = new ExpressionParserContext(); + parserContext.Functions.Add("v", new List() { new CustomFunction()}); + + // act and assert + parser.Parse("1 + v(2,0) + 3", parserContext).Value(context); + } + [Fact] public void When_ExpressionHasKnownParameter_Expect_Reference() { @@ -45,6 +80,7 @@ public void When_ExpressionHasSinFunction_Expect_Reference() Assert.Equal(1, parser.Parse("sin(0) + 1", new ExpressionParserContext(context.Functions)).Value(new ExpressionEvaluationContext() { ExpressionContext = context })); } + [Fact] public void When_ExpressionHasParameters_Expect_Reference() { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentExport.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentExport.cs index fd734826..8d9abe1f 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentExport.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentExport.cs @@ -12,8 +12,8 @@ public class CurrentExport : Export /// Initializes a new instance of the class. /// /// Name of export. - /// A simulation - /// A identifier + /// A simulation. + /// A name of current source. public CurrentExport(string name, Simulation simulation, string source) : base(simulation) { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentImaginaryExport.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentImaginaryExport.cs index cc8a4c44..68089866 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentImaginaryExport.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/CurrentExports/CurrentImaginaryExport.cs @@ -13,8 +13,8 @@ public class CurrentImaginaryExport : Export /// Initializes a new instance of the class. /// /// Name of export. - /// A simulation - /// An identifier + /// A simulation. + /// A name of current source. public CurrentImaginaryExport(string name, Simulation simulation, string source) : base(simulation) { @@ -24,30 +24,30 @@ public CurrentImaginaryExport(string name, Simulation simulation, string source) } /// - /// Gets the main node + /// Gets the main node. /// public string Source { get; } /// - /// Gets the type name + /// Gets the type name. /// public override string TypeName => "current"; /// - /// Gets the quantity unit + /// Gets the quantity unit. /// public override string QuantityUnit => "Current (A)"; /// - /// Gets the complex property export + /// Gets the complex property export. /// protected ComplexPropertyExport ExportImpl { get; } /// - /// Extracts current imaginary value + /// Extracts current imaginary value. /// /// - /// Current imaginary value + /// Current imaginary value. /// public override double Extract() { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExports/VoltageDecibelExport.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExports/VoltageDecibelExport.cs index a354fcec..c25df034 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExports/VoltageDecibelExport.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExports/VoltageDecibelExport.cs @@ -12,9 +12,9 @@ public class VoltageDecibelExport : Export /// Initializes a new instance of the class. /// /// Name of export. - /// Simulation - /// Positive node - /// Negative reference node + /// Simulation. + /// Positive node. + /// Negative reference node. public VoltageDecibelExport(string name, Simulation simulation, string node, string reference = null) : base(simulation) { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CircuitTemperatureSimulationDecorator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CircuitTemperatureSimulationDecorator.cs index 2e02c526..efe8e95d 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CircuitTemperatureSimulationDecorator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CircuitTemperatureSimulationDecorator.cs @@ -3,15 +3,22 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Decorators { - public class CircuitTemperatureSimulationDecorator + public class CircuitTemperatureSimulationDecorator : ISimulationDecorator { - public static BaseSimulation Decorate(BaseSimulation simulation, double circuitTemperature) + private readonly double _circuitTemperature; + + public CircuitTemperatureSimulationDecorator(double circuitTemperature) + { + _circuitTemperature = circuitTemperature; + } + + public BaseSimulation Decorate(BaseSimulation simulation) { EventHandler setState = (object sender, LoadStateEventArgs e) => { if (e.State is BaseSimulationState rs) { - rs.Temperature = circuitTemperature; + rs.Temperature = _circuitTemperature; } // TODO: What to do with complex state? diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CreateSimulationWithStochasticModelsDecorator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CreateSimulationWithStochasticModelsDecorator.cs deleted file mode 100644 index 7c397afe..00000000 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/CreateSimulationWithStochasticModelsDecorator.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using SpiceSharp; -using SpiceSharp.Circuits; -using SpiceSharp.Simulations; -using SpiceSharpParser.Common; -using SpiceSharpParser.Common.Evaluation; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; -using SpiceSharpParser.Models.Netlist.Spice.Objects; -using SpiceSharpParser.Models.Netlist.Spice.Objects.Parameters; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Decorators -{ - public class CreateSimulationWithStochasticModelsDecorator - { - private static readonly ConcurrentDictionary> LotValues = new ConcurrentDictionary>(); - - public static Func Decorate(IReadingContext context, Func createSimulation) - { - return (string simulationName, Control control, IReadingContext context2) => - { - var simulation = createSimulation(simulationName, control, context2); - var modelsRegistry = context.ModelsRegistry as IStochasticModelsRegistry; - - if (modelsRegistry != null) - { - simulation.BeforeExecute += (object sender, BeforeExecuteEventArgs arg) => - { - foreach (var stochasticModels in modelsRegistry.GetStochasticModels()) - { - var baseModel = stochasticModels.Key; - var componentModels = stochasticModels.Value; - - foreach (var componentModel in componentModels) - { - Dictionary stochasticDevParameters = modelsRegistry.GetStochasticModelDevParameters(baseModel); - - if (stochasticDevParameters != null) - { - SetModelDevModelParameters(context, simulation, baseModel, componentModel, stochasticDevParameters); - } - - Dictionary stochasticLotParameters = modelsRegistry.GetStochasticModelLotParameters(baseModel); - if (stochasticLotParameters != null) - { - SetModelLotModelParameters(context, simulation, baseModel, componentModel, stochasticLotParameters); - } - } - } - }; - } - - return simulation; - }; - } - - private static void SetModelLotModelParameters(IReadingContext context, BaseSimulation sim, Entity baseModel, Entity componentModel, Dictionary stochasticLotParameters) - { - var comparer = StringComparerProvider.Get(context.CaseSensitivity.IsEntityParameterNameCaseSensitive); - foreach (var stochasticParameter in stochasticLotParameters) - { - var parameter = stochasticParameter.Key; - var parameterPercent = stochasticParameter.Value; - - if (parameter is AssignmentParameter asg) - { - var evaluator = context.SimulationEvaluators.GetEvaluator(sim); - - var parameterName = asg.Name; - var currentValueParameter = sim.EntityParameters[componentModel.Name].GetParameter>(parameterName, comparer); - var expressionContext = context.SimulationExpressionContexts.GetContext(sim); - - var currentValue = currentValueParameter.Value; - var percentValue = evaluator.EvaluateValueExpression(parameterPercent.Tolerance.Image, expressionContext); - double newValue = GetValueForLotParameter(expressionContext, baseModel, parameterName, currentValue, percentValue, parameterPercent.RandomDistributionName, comparer); - context.SimulationPreparations.SetParameter(componentModel, sim, parameterName, newValue, true, false); - } - } - } - - private static void SetModelDevModelParameters(IReadingContext context, BaseSimulation sim, Entity baseModel, Entity componentModel, Dictionary stochasticDevParameters) - { - var comparer = StringComparerProvider.Get(context.CaseSensitivity.IsEntityParameterNameCaseSensitive); - foreach (var stochasticParameter in stochasticDevParameters) - { - var parameter = stochasticParameter.Key; - var parameterPercent = stochasticParameter.Value; - - if (parameter is AssignmentParameter asg) - { - var evaluator = context.SimulationEvaluators.GetEvaluator(sim); - - var asgparamName = asg.Name; - var currentValueParameter = sim.EntityParameters[componentModel.Name].GetParameter>(asgparamName, comparer); - var currentValue = currentValueParameter.Value; - var expressionContext = context.SimulationExpressionContexts.GetContext(sim); - var percentValue = evaluator.EvaluateValueExpression(parameterPercent.Tolerance.Image, expressionContext); - - double newValue = GetValueForDevParameter(expressionContext, currentValue, percentValue, parameterPercent.RandomDistributionName); - context.SimulationPreparations.SetParameter(componentModel, sim, asgparamName, newValue, true, false); - } - } - } - - private static double GetValueForDevParameter(ExpressionContext expressionContext, double currentValue, double percentValue, string distributionName) - { - var random = expressionContext.Randomizer.GetRandomProvider(expressionContext.Seed, distributionName); - var r = random.NextSignedDouble(); - double newValue = currentValue + (percentValue / 100.0 * currentValue * r); - return newValue; - } - - private static double GetValueForLotParameter(ExpressionContext expressionContext, Entity baseModel, string parameterName, double currentValue, double percentValue, string distributionName, IEqualityComparer comparer) - { - if (LotValues.ContainsKey(baseModel) && LotValues[baseModel].ContainsKey(parameterName)) - { - return LotValues[baseModel][parameterName]; - } - - var random = expressionContext.Randomizer.GetRandomProvider(expressionContext.Seed, distributionName); - double newValue = currentValue + (percentValue / 100.0 * currentValue * random.NextSignedDouble()); - - if (!LotValues.ContainsKey(baseModel)) - { - LotValues[baseModel] = new Dictionary(comparer); - } - - LotValues[baseModel][parameterName] = newValue; - - return newValue; - } - } -} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs new file mode 100644 index 00000000..d4e41db8 --- /dev/null +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs @@ -0,0 +1,134 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using SpiceSharp; +using SpiceSharp.Circuits; +using SpiceSharp.Simulations; +using SpiceSharpParser.Common; +using SpiceSharpParser.Common.Evaluation; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; +using SpiceSharpParser.Models.Netlist.Spice.Objects; +using SpiceSharpParser.Models.Netlist.Spice.Objects.Parameters; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Decorators +{ + public class EnableStochasticModelsSimulationDecorator + { + private readonly IReadingContext _context; + private readonly ConcurrentDictionary> LotValues = new ConcurrentDictionary>(); + + public EnableStochasticModelsSimulationDecorator(IReadingContext context) + { + _context = context; + } + + public BaseSimulation Decorate(BaseSimulation simulation) + { + var modelsRegistry = _context.ModelsRegistry as IStochasticModelsRegistry; + + if (modelsRegistry != null) + { + simulation.BeforeExecute += (object sender, BeforeExecuteEventArgs arg) => + { + foreach (var stochasticModels in modelsRegistry.GetStochasticModels()) + { + var baseModel = stochasticModels.Key; + var componentModels = stochasticModels.Value; + + foreach (var componentModel in componentModels) + { + Dictionary stochasticDevParameters = modelsRegistry.GetStochasticModelDevParameters(baseModel); + if (stochasticDevParameters != null) + { + SetModelDevModelParameters(simulation, baseModel, componentModel, stochasticDevParameters); + } + + Dictionary stochasticLotParameters = modelsRegistry.GetStochasticModelLotParameters(baseModel); + if (stochasticLotParameters != null) + { + SetModelLotModelParameters(simulation, baseModel, componentModel, stochasticLotParameters); + } + } + } + }; + } + + return simulation; + } + + private void SetModelLotModelParameters(BaseSimulation sim, Entity baseModel, Entity componentModel, Dictionary stochasticLotParameters) + { + var comparer = StringComparerProvider.Get(_context.CaseSensitivity.IsEntityParameterNameCaseSensitive); + foreach (var stochasticParameter in stochasticLotParameters) + { + var parameter = stochasticParameter.Key; + var parameterPercent = stochasticParameter.Value; + + if (parameter is AssignmentParameter asg) + { + var evaluator = _context.SimulationEvaluators.GetEvaluator(sim); + + var parameterName = asg.Name; + var currentValueParameter = sim.EntityParameters[componentModel.Name].GetParameter>(parameterName, comparer); + var expressionContext = _context.SimulationExpressionContexts.GetContext(sim); + + var currentValue = currentValueParameter.Value; + var percentValue = evaluator.EvaluateValueExpression(parameterPercent.Tolerance.Image, expressionContext); + double newValue = GetValueForLotParameter(expressionContext, baseModel, parameterName, currentValue, percentValue, parameterPercent.RandomDistributionName, comparer); + _context.SimulationPreparations.SetParameter(componentModel, sim, parameterName, newValue, true, false); + } + } + } + + private void SetModelDevModelParameters(BaseSimulation sim, Entity baseModel, Entity componentModel, Dictionary stochasticDevParameters) + { + var comparer = StringComparerProvider.Get(_context.CaseSensitivity.IsEntityParameterNameCaseSensitive); + foreach (var stochasticParameter in stochasticDevParameters) + { + var parameter = stochasticParameter.Key; + var parameterPercent = stochasticParameter.Value; + + if (parameter is AssignmentParameter assignmentParameter) + { + var evaluator = _context.SimulationEvaluators.GetEvaluator(sim); + + var parameterName = assignmentParameter.Name; + var currentValueParameter = sim.EntityParameters[componentModel.Name].GetParameter>(parameterName, comparer); + var currentValue = currentValueParameter.Value; + var expressionContext = _context.SimulationExpressionContexts.GetContext(sim); + var percentValue = evaluator.EvaluateValueExpression(parameterPercent.Tolerance.Image, expressionContext); + + double newValue = GetValueForDevParameter(expressionContext, currentValue, percentValue, parameterPercent.RandomDistributionName); + _context.SimulationPreparations.SetParameter(componentModel, sim, parameterName, newValue, true, false); + } + } + } + + private double GetValueForDevParameter(ExpressionContext expressionContext, double currentValue, double percentValue, string distributionName) + { + var random = expressionContext.Randomizer.GetRandomProvider(expressionContext.Seed, distributionName); + var r = random.NextSignedDouble(); + return currentValue + (percentValue / 100.0 * currentValue * r); + } + + private double GetValueForLotParameter(ExpressionContext expressionContext, Entity baseModel, string parameterName, double currentValue, double percentValue, string distributionName, IEqualityComparer comparer) + { + if (LotValues.ContainsKey(baseModel) && LotValues[baseModel].ContainsKey(parameterName)) + { + return LotValues[baseModel][parameterName]; + } + + var random = expressionContext.Randomizer.GetRandomProvider(expressionContext.Seed, distributionName); + double newValue = currentValue + (percentValue / 100.0 * currentValue * random.NextSignedDouble()); + + if (!LotValues.ContainsKey(baseModel)) + { + LotValues[baseModel] = new Dictionary(comparer); + } + + LotValues[baseModel][parameterName] = newValue; + + return newValue; + } + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/NominalTemperatureSimulationDecorator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/NominalTemperatureSimulationDecorator.cs index d5962cdf..803da515 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/NominalTemperatureSimulationDecorator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/NominalTemperatureSimulationDecorator.cs @@ -3,15 +3,22 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Decorators { - public class NominalTemperatureSimulationDecorator + public class NominalTemperatureSimulationDecorator : ISimulationDecorator { - public static BaseSimulation Decorate(BaseSimulation simulation, double nominalTemperatureInKelvins) + private readonly double _nominalTemperatureInKelvins; + + public NominalTemperatureSimulationDecorator(double nominalTemperatureInKelvins) + { + _nominalTemperatureInKelvins = nominalTemperatureInKelvins; + } + + public BaseSimulation Decorate(BaseSimulation simulation) { EventHandler setState = (object sender, LoadStateEventArgs e) => { if (e.State is BaseSimulationState rs) { - rs.NominalTemperature = nominalTemperatureInKelvins; + rs.NominalTemperature = _nominalTemperatureInKelvins; } // TODO: What to do with complex state? diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllParameterSweepsAndTemperaturesFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllParameterSweepsAndTemperaturesFactory.cs index e16f0d92..e528a8c0 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllParameterSweepsAndTemperaturesFactory.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllParameterSweepsAndTemperaturesFactory.cs @@ -14,11 +14,13 @@ public class CreateSimulationsForAllParameterSweepsAndTemperaturesFactory : ICre { public CreateSimulationsForAllParameterSweepsAndTemperaturesFactory(ICreateSimulationsForAllTemperaturesFactory allTemperaturesFactory) { - AllTemperaturesFactory = allTemperaturesFactory; - + AllTemperaturesFactory = allTemperaturesFactory ?? throw new ArgumentNullException(nameof(allTemperaturesFactory)); ParameterUpdater = new ParameterSweepUpdater(); } + /// + /// Gets the simulations factory. + /// public ICreateSimulationsForAllTemperaturesFactory AllTemperaturesFactory { get; } /// @@ -26,12 +28,29 @@ public CreateSimulationsForAllParameterSweepsAndTemperaturesFactory(ICreateSimul /// protected IParameterSweepUpdater ParameterUpdater { get; } + /// + /// Creates simulations for all parameter and temperature sweeps. + /// + /// Statement. + /// Context. + /// Create simulation factory. + /// public List CreateSimulations(Control statement, IReadingContext context, Func createSimulation) { var result = new List(); ProcessTempParameterSweep(context); + if (context.Result.SimulationConfiguration.ParameterSweeps.Count == 0) + { + result.AddRange(AllTemperaturesFactory.CreateSimulations( + statement, + context, + createSimulation)); + + return result; + } + List> sweeps = new List>(); int productCount = 1; @@ -51,7 +70,8 @@ public List CreateSimulations(Control statement, IReadingContext Func createSimulationWithSweepParametersFactory = (name, control, modifiedContext) => { - List> parameterValues = GetSweepParameterValues(context, sweeps, system, indexes); + List> parameterValues = + GetSweepParameterValues(context, sweeps, system, indexes); string suffix = GetSimulationNameSuffix(parameterValues); var simulation = createSimulation(name + " (" + suffix + ")", control, modifiedContext); diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllTemperaturesFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllTemperaturesFactory.cs index 8293fedc..b99f6fd0 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllTemperaturesFactory.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForAllTemperaturesFactory.cs @@ -11,7 +11,7 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulatio { public class CreateSimulationsForAllTemperaturesFactory : ICreateSimulationsForAllTemperaturesFactory { - public IEnumerable CreateSimulations(Control statement, IReadingContext context, Func createSimulation) + public List CreateSimulations(Control statement, IReadingContext context, Func createSimulation) { var result = new List(); @@ -63,12 +63,14 @@ protected void SetSimulationTemperatures(BaseSimulation simulation, double? oper { if (operatingTemperatureInKelvins.HasValue) { - CircuitTemperatureSimulationDecorator.Decorate(simulation, operatingTemperatureInKelvins.Value); + var decorator = new CircuitTemperatureSimulationDecorator(operatingTemperatureInKelvins.Value); + decorator.Decorate(simulation); } if (nominalTemperatureInKelvins.HasValue) { - NominalTemperatureSimulationDecorator.Decorate(simulation, nominalTemperatureInKelvins.Value); + var decorator = new NominalTemperatureSimulationDecorator(nominalTemperatureInKelvins.Value); + decorator.Decorate(simulation); } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs index e7518004..4a68bb3e 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs @@ -3,64 +3,61 @@ using System.Linq; using SpiceSharp.Simulations; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.Models.Netlist.Spice.Objects; using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.Models.Netlist.Spice.Objects; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Factories { public class CreateSimulationsForMonteCarloFactory : ICreateSimulationsForMonteCarloFactory { public CreateSimulationsForMonteCarloFactory( - ICreateSimulationsForAllTemperaturesFactory allTemperatures, - ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory allTemperaturesAndSweeps, + ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory temperatureAndParameterSweepsSimulationFactory, IExportFactory exportFactory, IMapper mapperExporter) { - AllTemperaturesAndSweeps = allTemperaturesAndSweeps; + TemperatureAndParameterSweepsSimulationFactory = temperatureAndParameterSweepsSimulationFactory; ExportFactory = exportFactory; - AllTemperatures = allTemperatures; MapperExporter = mapperExporter; } - public IMapper MapperExporter { get; set; } + /// + /// Gets the exporter mapper. + /// + protected IMapper MapperExporter { get; } - public ICreateSimulationsForAllTemperaturesFactory AllTemperatures { get; } + /// + /// Gets the simulations factory. + /// + protected ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory TemperatureAndParameterSweepsSimulationFactory { get; } - public ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory AllTemperaturesAndSweeps { get; } + /// + /// Gets the export factory. + /// + protected IExportFactory ExportFactory { get; } - public IExportFactory ExportFactory { get; } - - public List Create(Control statement, IReadingContext context, Func simulationWithStochasticModels) + /// + /// Creates simulations for Monte Carlo simulation. + /// + /// Statement/ + /// Context. + /// Simulation factory. + /// + public List Create(Control statement, IReadingContext context, Func createSimulation) { context.Result.MonteCarlo.Enabled = true; context.Result.MonteCarlo.Seed = context.Result.SimulationConfiguration.MonteCarloConfiguration.Seed; - context.Result.MonteCarlo.OutputVariable = - context.Result.SimulationConfiguration.MonteCarloConfiguration.OutputVariable.Image; + context.Result.MonteCarlo.OutputVariable = context.Result.SimulationConfiguration.MonteCarloConfiguration.OutputVariable.Image; context.Result.MonteCarlo.Function = context.Result.SimulationConfiguration.MonteCarloConfiguration.Function; var result = new List(); - if (context.Result.SimulationConfiguration.ParameterSweeps.Count == 0) + for (var i = 0; i < context.Result.SimulationConfiguration.MonteCarloConfiguration.Runs; i++) { - for (var i = 0; i < context.Result.SimulationConfiguration.MonteCarloConfiguration.Runs; i++) - { - var simulations = AllTemperatures - .CreateSimulations(statement, context, simulationWithStochasticModels).ToList(); - - AttachMonteCarloDataGathering(context, simulations); - result.AddRange(simulations); - } - } - else - { - for (var i = 0; i < context.Result.SimulationConfiguration.MonteCarloConfiguration.Runs; i++) - { - var simulations = AllTemperaturesAndSweeps.CreateSimulations(statement, context, simulationWithStochasticModels); - AttachMonteCarloDataGathering(context, simulations); - result.AddRange(simulations); - } + var simulations = TemperatureAndParameterSweepsSimulationFactory.CreateSimulations(statement, context, createSimulation); + AttachMonteCarloDataGathering(context, simulations); + result.AddRange(simulations); } return result; @@ -80,7 +77,7 @@ protected void AttachMonteCarloDataGatheringForSimulation(IReadingContext contex simulation.BeforeSetup += (sender, args) => { - Export export = context.Result.Exports.FirstOrDefault(e => e.Simulation == simulation && e.Name == exportParam.Image); + Export export = context.Result.Exports.FirstOrDefault(e => e.Simulation == simulation && e.Name == exportParam.Image); if (export == null) { @@ -88,13 +85,13 @@ protected void AttachMonteCarloDataGatheringForSimulation(IReadingContext contex } simulation.ExportSimulationData += (exportSender, exportArgs) => + { + if (export != null) { - if (export != null) - { - var value = export.Extract(); - context.Result.MonteCarlo.Collect(simulation, value); - } - }; + var value = export.Extract(); + context.Result.MonteCarlo.Collect(simulation, value); + } + }; }; } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForAllTemperaturesFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForAllTemperaturesFactory.cs index 40d70707..ab49e59f 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForAllTemperaturesFactory.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForAllTemperaturesFactory.cs @@ -8,6 +8,6 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulatio { public interface ICreateSimulationsForAllTemperaturesFactory { - IEnumerable CreateSimulations(Control statement, IReadingContext context, Func createSimulation); + List CreateSimulations(Control statement, IReadingContext context, Func createSimulation); } } \ No newline at end of file diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForMonteCarloFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForMonteCarloFactory.cs index 12f50c46..a8749ddc 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForMonteCarloFactory.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/ICreateSimulationsForMonteCarloFactory.cs @@ -8,6 +8,6 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulatio { public interface ICreateSimulationsForMonteCarloFactory { - List Create(Control statement, IReadingContext context, Func simulationWithStochasticModels); + List Create(Control statement, IReadingContext context, Func createSimulation); } } \ No newline at end of file diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationDecorator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationDecorator.cs new file mode 100644 index 00000000..ecb178e8 --- /dev/null +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationDecorator.cs @@ -0,0 +1,9 @@ +using SpiceSharp.Simulations; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations +{ + public interface ISimulationDecorator + { + BaseSimulation Decorate(BaseSimulation simulation); + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationsFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationsFactory.cs new file mode 100644 index 00000000..5685b161 --- /dev/null +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/ISimulationsFactory.cs @@ -0,0 +1,12 @@ +using System; +using SpiceSharp.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.Models.Netlist.Spice.Objects; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations +{ + public interface ISimulationsFactory + { + void Create(Control statement, IReadingContext context, Func createSimulation); + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationControl.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationControl.cs index 5d7efa42..8f15bb1e 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationControl.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationControl.cs @@ -2,12 +2,8 @@ using SpiceSharp.Simulations; using SpiceSharpParser.Common; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Decorators; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Factories; using SpiceSharpParser.Models.Netlist.Spice.Objects; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations @@ -17,30 +13,14 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulatio /// public abstract class SimulationControl : BaseControl { + private readonly ISimulationsFactory _factory; + /// /// Initializes a new instance of the class. /// protected SimulationControl(IMapper exporterMapper) { - CreateSimulationsForAllTemperaturesFactory = new CreateSimulationsForAllTemperaturesFactory(); - CreateSimulationsForAllParameterSweepsAndTemperaturesFactory = new CreateSimulationsForAllParameterSweepsAndTemperaturesFactory(CreateSimulationsForAllTemperaturesFactory); - CreateSimulationsForMonteCarloFactory = new CreateSimulationsForMonteCarloFactory( - CreateSimulationsForAllTemperaturesFactory, - CreateSimulationsForAllParameterSweepsAndTemperaturesFactory, - new ExportFactory(), - exporterMapper); - } - - public ICreateSimulationsForAllTemperaturesFactory CreateSimulationsForAllTemperaturesFactory { get; private set; } - - public ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory CreateSimulationsForAllParameterSweepsAndTemperaturesFactory { get; private set; } - - public ICreateSimulationsForMonteCarloFactory CreateSimulationsForMonteCarloFactory { get; } - - protected static bool IsMonteCarloEnabledForSimulation(Control statement, IReadingContext context) - { - return context.Result.SimulationConfiguration.MonteCarloConfiguration.Enabled - && statement.Name.ToLower() == context.Result.SimulationConfiguration.MonteCarloConfiguration.SimulationType.ToLower(); + _factory = new SimulationsFactory(exporterMapper); } /// @@ -48,40 +28,7 @@ protected static bool IsMonteCarloEnabledForSimulation(Control statement, IReadi /// protected void CreateSimulations(Control statement, IReadingContext context, Func createSimulation) { - if (context.ModelsRegistry is StochasticModelsRegistry) - { - createSimulation = CreateSimulationWithStochasticModelsDecorator.Decorate(context, createSimulation); - } - - if (!IsMonteCarloEnabledForSimulation(statement, context)) - { - if (context.Result.SimulationConfiguration.ParameterSweeps.Count == 0) - { - var simulations = CreateSimulationsForAllTemperaturesFactory.CreateSimulations(statement, context, createSimulation); - - foreach (var simulation in simulations) - { - context.SimulationPreparations.Prepare(simulation); - } - } - else - { - var simulations = CreateSimulationsForAllParameterSweepsAndTemperaturesFactory.CreateSimulations(statement, context, createSimulation); - foreach (var simulation in simulations) - { - context.SimulationPreparations.Prepare(simulation); - } - } - } - else - { - var simulations = CreateSimulationsForMonteCarloFactory.Create(statement, context, createSimulation); - - foreach (var simulation in simulations) - { - context.SimulationPreparations.Prepare(simulation); - } - } + _factory.Create(statement, context, createSimulation); } /// diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationsFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationsFactory.cs new file mode 100644 index 00000000..5c8b69b6 --- /dev/null +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/SimulationsFactory.cs @@ -0,0 +1,71 @@ +using System; +using SpiceSharp.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Decorators; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Factories; +using SpiceSharpParser.Models.Netlist.Spice.Objects; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations +{ + public class SimulationsFactory : ISimulationsFactory + { + public SimulationsFactory(IMapper exporterMapper) + { + var temp = new CreateSimulationsForAllTemperaturesFactory(); + + CreateSimulationsForAllParameterSweepsAndTemperaturesFactory = new CreateSimulationsForAllParameterSweepsAndTemperaturesFactory(temp); + CreateSimulationsForMonteCarloFactory = new CreateSimulationsForMonteCarloFactory(CreateSimulationsForAllParameterSweepsAndTemperaturesFactory, new ExportFactory(), exporterMapper); + } + + /// + /// Gets the simulations factory that creates simulations parameter and temperature sweeps. + /// + protected ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory CreateSimulationsForAllParameterSweepsAndTemperaturesFactory { get; } + + /// + /// Gets the simulations factory that creates simulations for Monte Carol simulation. + /// + protected ICreateSimulationsForMonteCarloFactory CreateSimulationsForMonteCarloFactory { get; } + + /// + /// Creates simulations. + /// + /// Simulation statement. + /// Context. + /// Simulation factory. + public void Create(Control statement, IReadingContext context, Func createSimulation) + { + if (!IsMonteCarloEnabledForSimulation(statement, context)) + { + var simulations = CreateSimulationsForAllParameterSweepsAndTemperaturesFactory.CreateSimulations(statement, context, createSimulation); + foreach (var simulation in simulations) + { + var stochasticDecorator = new EnableStochasticModelsSimulationDecorator(context); + stochasticDecorator.Decorate(simulation); + + context.SimulationPreparations.Prepare(simulation); + } + } + else + { + var simulations = CreateSimulationsForMonteCarloFactory.Create(statement, context, createSimulation); + foreach (var simulation in simulations) + { + var stochasticDecorator = new EnableStochasticModelsSimulationDecorator(context); + stochasticDecorator.Decorate(simulation); + + context.SimulationPreparations.Prepare(simulation); + } + } + } + + protected static bool IsMonteCarloEnabledForSimulation(Control statement, IReadingContext context) + { + return context.Result.SimulationConfiguration.MonteCarloConfiguration.Enabled + && statement.Name.ToLower() == context.Result.SimulationConfiguration.MonteCarloConfiguration.SimulationType.ToLower(); + } + } +} diff --git a/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs b/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs index 7dcbddcb..3f9c5fc5 100644 --- a/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs +++ b/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs @@ -357,111 +357,149 @@ public ExpressionParseResult Parse(string expression, ExpressionParserContext co } else if (c == '.' || (c >= '0' && c <= '9')) { - if (operatorStack.Count > 0 - && operatorStack.FirstOrDefault(o => o.Id == IdFunction) != null) + infixPostfix = true; + + if (operatorStack.Count > 0 && operatorStack.Peek() is FunctionOperator fo && fo.Functions.First() is IFunction) { - if (operatorStack.Peek() is FunctionOperator fo && fo.Functions.First() is IFunction) + int startIndex = index; + + while (index < expression.Length) { - int startIndex = index; + if (expression[index] == ')') + { + break; + } - while (index < expression.Length) + if (expression[index] == ',') { - if (expression[index] == ',') - { - break; - } + break; + } - if (expression[index] == ')') - { - break; - } + if (expression[index] == '[') + { + break; + } - index++; + if (expression[index] == ']') + { + break; } - var virtualParameter = expression.Substring(startIndex, index - startIndex); - stringParametersStack.Push(virtualParameter); - } - else - { - double parseResult = ParseDouble(expression, ref index); - outputStack.Push((evalContext) => parseResult); + index++; } + + var stringParameter = expression.Substring(startIndex, index - startIndex); + stringParametersStack.Push(stringParameter); + infixPostfix = true; } else { double parseResult = ParseDouble(expression, ref index); outputStack.Push((evalContext) => parseResult); } - - infixPostfix = true; } - // Parse a parameter or a function else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || (c == '.')) { - sb.Clear(); - sb.Append(input[index++]); - while (index < count) + if (operatorStack.Count > 0 && operatorStack.Peek() is FunctionOperator fo && fo.Functions.First() is IFunction) { - c = input[index]; - if ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - c == '_' || - c == '.') - { - sb.Append(c); - index++; - } - else + int startIndex = index; + + while (index < expression.Length) { - break; - } - } + if (expression[index] == ')') + { + break; + } - if (index < count && input[index] == '(') - { - index++; - var functionName = sb.ToString(); + if (expression[index] == ',') + { + break; + } - if (context.Functions.ContainsKey(functionName)) - { - foundFunctions.Add(functionName); - operatorStack.Push(CreateOperatorForFunction(functionName, index, context)); - } - else - { - throw new FunctionNotFoundException(functionName); + if (expression[index] == '[') + { + break; + } + + if (expression[index] == ']') + { + break; + } + + index++; } + + var stringParameter = expression.Substring(startIndex, index - startIndex); + stringParametersStack.Push(stringParameter); + infixPostfix = true; } else { - string parameterName = sb.ToString(); + sb.Clear(); + sb.Append(input[index++]); + while (index < count) + { + c = input[index]; + if ((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_' || + c == '.') + { + sb.Append(c); + index++; + } + else + { + break; + } + } - if (operatorStack.Count > 0 && operatorStack.Peek().Id == IdFunction - && ((FunctionOperator)operatorStack.Peek()).Functions.First() is IFunction) + if (index < count && input[index] == '(') { - stringParametersStack.Push(parameterName); + index++; + var functionName = sb.ToString(); + + if (context.Functions.ContainsKey(functionName)) + { + foundFunctions.Add(functionName); + operatorStack.Push(CreateOperatorForFunction(functionName, index, context)); + } + else + { + throw new FunctionNotFoundException(functionName); + } } else { - foundParameters.Add(parameterName); - outputStack.Push((evalContext) => + string parameterName = sb.ToString(); + + if (operatorStack.Count > 0 && operatorStack.Peek().Id == IdFunction + && ((FunctionOperator) operatorStack.Peek()).Functions + .First() is IFunction) + { + stringParametersStack.Push(parameterName); + } + else { - if (!evalContext.ExpressionContext.Parameters.ContainsKey(parameterName)) + foundParameters.Add(parameterName); + outputStack.Push((evalContext) => { - throw new UnknownParameterException() { Name = parameterName }; - } - - return evalContext.ExpressionContext.Parameters[parameterName].Evaluate(evalContext.Evaluator, evalContext.ExpressionContext); - }); + if (!evalContext.ExpressionContext.Parameters.ContainsKey(parameterName)) + { + throw new UnknownParameterException() {Name = parameterName}; + } + + return evalContext.ExpressionContext.Parameters[parameterName] + .Evaluate(evalContext.Evaluator, evalContext.ExpressionContext); + }); + } + infixPostfix = true; } - - infixPostfix = true; } } - else if (input[index] == ')' && index >= 1 && input[index - 1] == '(') + else if (input[index] == ')') { while (operatorStack.Count > 0) { @@ -615,7 +653,7 @@ private void EvaluateFunction(string expression, FunctionOperator op, int? endIn if (!(function is IFunction df)) { - throw new InvalidOperationException("Virtual function needs to have double as arguments"); + throw new InvalidOperationException("Function needs to have double as arguments"); } var args = PopAndReturnArguments(outputStack, functionArguments); From e44d7e836c92402ab7f53a751f55569c9ca0ae28 Mon Sep 17 00:00:00 2001 From: Marcin Date: Mon, 22 Jul 2019 23:52:31 +0200 Subject: [PATCH 2/6] Fix LOT in .MC simulations --- .../Netlist/Spice/Context/IReadingContext.cs | 3 +- .../Spice/Context/ISimulationPreparations.cs | 5 +- .../Spice/Context/Models/IModelsRegistry.cs | 3 +- .../Models/IStochasticModelsRegistry.cs | 6 +- .../Models/StochasticModelsRegistry.cs | 33 +- .../Netlist/Spice/Context/ReadingContext.cs | 6 +- .../Spice/Context/SimulationPreparations.cs | 17 + .../Spice/Context/Updates/EntityUpdates.cs | 8 +- .../Export/OrdinaryExportFunction.cs | 2 +- .../Evaluation/Functions/Math/PosFunction.cs | 26 ++ .../Evaluation/Functions/MathFunctions.cs | 11 + .../Evaluation/SpiceExpressionContext.cs | 1 + .../Readers/Controls/Exporters/Export.cs | 2 +- .../Controls/Exporters/PropertyExporter.cs | 28 +- .../Controls/Exporters/VoltageExporter.cs | 1 + .../Readers/Controls/Exporters/ZeroExport.cs | 19 + .../Spice/Readers/Controls/PlotControl.cs | 396 +++++++++--------- ...ableStochasticModelsSimulationDecorator.cs | 8 +- .../CreateSimulationsForMonteCarloFactory.cs | 172 ++++---- .../Controls/Simulations/MonteCarloResult.cs | 10 +- .../Components/RLCKGenerator.cs | 33 +- .../BipolarJunctionTransistorGenerator.cs | 16 +- .../Semiconductors/DiodeGenerator.cs | 16 +- .../Semiconductors/JFETGenerator.cs | 16 +- .../Semiconductors/MosfetGenerator.cs | 16 +- .../Components/SwitchGenerator.cs | 68 ++- .../StochasticModelsGenerator.cs | 2 +- .../Expression/SpiceExpressionParser.cs | 2 +- 28 files changed, 544 insertions(+), 382 deletions(-) create mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Math/PosFunction.cs create mode 100644 src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/ZeroExport.cs diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs index 9d48a225..7334fdb1 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs @@ -139,7 +139,8 @@ public interface IReadingContext /// Parameter name. /// Value expression. /// Should be re-evaluated OnBeforeLoad. - void SetParameter(Entity entity, string parameterName, string valueExpression, bool onload = true); + void SetParameter(Entity entity, string parameterName, string valueExpression, bool onload = true, + bool beforeTemperature = true); /// /// Sets the initial voltage. diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ISimulationPreparations.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ISimulationPreparations.cs index 6964bc54..94fd0ada 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ISimulationPreparations.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ISimulationPreparations.cs @@ -1,4 +1,5 @@ -using SpiceSharp.Circuits; +using System; +using SpiceSharp.Circuits; using SpiceSharp.Simulations; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context @@ -18,5 +19,7 @@ public interface ISimulationPreparations void SetParameter(Entity @object, BaseSimulation simulation, string paramName, double value, bool beforeTemperature, bool onload); void ExecuteTemperatureBehaviorBeforeLoad(Entity @object); + + void ExecuteActionBeforeSetup(Action action); } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IModelsRegistry.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IModelsRegistry.cs index 33436c87..44b86da2 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IModelsRegistry.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IModelsRegistry.cs @@ -2,13 +2,14 @@ using System.Collections.Generic; using SpiceSharp.Circuits; using SpiceSharp.Components; +using SpiceSharp.Simulations; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Names; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models { public interface IModelsRegistry { - void SetModel(Entity entity, string modelName, string exceptionMessage, Action setModelAction, IResultService result) + void SetModel(Entity entity, BaseSimulation simulation, string modelName, string exceptionMessage, Action setModelAction, IResultService result) where T : Model; T FindModel(string modelName) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IStochasticModelsRegistry.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IStochasticModelsRegistry.cs index 81c6999d..bc03cac9 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IStochasticModelsRegistry.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/IStochasticModelsRegistry.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using SpiceSharp.Circuits; using SpiceSharp.Components; +using SpiceSharp.Simulations; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models { @@ -20,7 +22,9 @@ void RegisterModelLot( SpiceSharpParser.Models.Netlist.Spice.Objects.Parameter tolerance, string distributionName); - Dictionary> GetStochasticModels(); + Model ProvideStochasticModel(string componentName, BaseSimulation sim, SpiceSharp.Components.Model model); + + Dictionary> GetStochasticModels(BaseSimulation sim); Dictionary GetStochasticModelDevParameters(Model baseModel); diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/StochasticModelsRegistry.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/StochasticModelsRegistry.cs index d9e355b0..b73bc425 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/StochasticModelsRegistry.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Models/StochasticModelsRegistry.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using SpiceSharp.Circuits; +using SpiceSharp.Simulations; using SpiceSharpParser.Common; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Names; using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; using SpiceSharpParser.Models.Netlist.Spice.Objects; +using Model = SpiceSharp.Components.Model; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models { @@ -43,7 +45,7 @@ public StochasticModelsRegistry(IEnumerable modelNamesGene /// /// Gets or sets the dictionary of stochastic models. /// - protected Dictionary> StochasticModels { get; set; } = new Dictionary>(); + protected Dictionary>> StochasticModels { get; set; } = new Dictionary>>(); /// /// Gets or sets the list of all models in the registry. @@ -142,25 +144,30 @@ public void RegisterModelLot( /// /// Provides a model for component. /// - /// A component. + /// A component name. /// A model for component. /// /// If a model is stochastic (dev, lot) then a copy of model with be returned. /// If a model is not stochastic then a raw model is returned. /// - public SpiceSharp.Components.Model ProvideStochasticModel(Entity component, SpiceSharp.Components.Model model) + public Model ProvideStochasticModel(string componentName, BaseSimulation simulation, SpiceSharp.Components.Model model) { if (ModelsGenerators.ContainsKey(model)) { - string modelId = string.Format("{0}#{1}", model.Name, component.Name); + string modelId = string.Format("{0}#{1}_{2}", model.Name, componentName, simulation.Name); var modelForComponent = ModelsGenerators[model](modelId); - if (!StochasticModels.ContainsKey(model)) + if (!StochasticModels.ContainsKey(simulation)) { - StochasticModels[model] = new List(); + StochasticModels[simulation] = new Dictionary>(); } - StochasticModels[model].Add(modelForComponent); + if (!StochasticModels[simulation].ContainsKey(model)) + { + StochasticModels[simulation][model] = new List(); + } + + StochasticModels[simulation][model].Add(modelForComponent); return modelForComponent; } @@ -173,9 +180,11 @@ public SpiceSharp.Components.Model ProvideStochasticModel(Entity component, Spic /// /// A dictionary of base models and their stochastic models. /// - public Dictionary> GetStochasticModels() + public Dictionary> GetStochasticModels(BaseSimulation simulation) { - return StochasticModels; + return StochasticModels.ContainsKey(simulation) + ? StochasticModels[simulation] + : new Dictionary>(); } /// @@ -221,7 +230,7 @@ public Dictionary GetStochasticModelLotParameter return null; } - public void SetModel(Entity entity, string modelName, string exceptionMessage, Action setModelAction, IResultService result) + public void SetModel(Entity entity, BaseSimulation simulation, string modelName, string exceptionMessage, Action setModelAction, IResultService result) where T : SpiceSharp.Components.Model { var model = FindModel(modelName); @@ -231,7 +240,7 @@ public void SetModel(Entity entity, string modelName, string exceptionMessage throw new ModelNotFoundException(exceptionMessage); } - var stochasticModel = (T) ProvideStochasticModel(entity, model); + var stochasticModel = (T) ProvideStochasticModel(entity.Name, simulation, model); setModelAction(stochasticModel); if (stochasticModel != null) @@ -266,7 +275,7 @@ public IModelsRegistry CreateChildRegistry(List generators result.AllModels = new Dictionary(AllModels, StringComparerProvider.Get(IsModelNameCaseSensitive)); result.ModelsWithDev = new Dictionary>(ModelsWithDev); result.ModelsWithLot = new Dictionary>(ModelsWithLot); - + result.StochasticModels = new Dictionary>>(StochasticModels); return result; } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs index 76e23997..8fc407bd 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs @@ -255,7 +255,7 @@ public void CreateNodes(SpiceSharp.Components.Component component, ParameterColl if (parameters.Count < component.PinCount) { throw new WrongParametersCountException( - "Too less parameters for: " + component.Name + " to create nodes"); + "Too few parameters for: " + component.Name + " to create nodes"); } string[] nodes = new string[component.PinCount]; @@ -344,7 +344,7 @@ public void SetNamedExpression(string expressionName, string expression) ReadingExpressionContext.SetNamedExpression(expressionName, expression, foundParameters); } - public void SetParameter(Entity entity, string parameterName, string expression, bool onload = true) + public void SetParameter(Entity entity, string parameterName, string expression, bool onload = true, bool beforeTemperature = true) { if (entity == null) { @@ -372,7 +372,7 @@ public void SetParameter(Entity entity, string parameterName, string expression, if (parseResult.IsConstantExpression == false) { - SimulationPreparations.SetParameter(entity, parameterName, expression, true, onload); + SimulationPreparations.SetParameter(entity, parameterName, expression, beforeTemperature, onload); } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/SimulationPreparations.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/SimulationPreparations.cs index 193a9601..54c33669 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/SimulationPreparations.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/SimulationPreparations.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using SpiceSharp.Behaviors; using SpiceSharp.Circuits; using SpiceSharp.Simulations; @@ -12,12 +13,15 @@ public SimulationPreparations(EntityUpdates entityUpdates, SimulationsUpdates si { EntityUpdates = entityUpdates ?? throw new ArgumentNullException(nameof(entityUpdates)); SimulationUpdates = simulationUpdates ?? throw new ArgumentNullException(nameof(simulationUpdates)); + BeforeExecute = new List>(); } protected EntityUpdates EntityUpdates { get; } protected SimulationsUpdates SimulationUpdates { get; } + protected List> BeforeExecute { get; } + public void Prepare(BaseSimulation simulation) { if (simulation == null) @@ -25,6 +29,14 @@ public void Prepare(BaseSimulation simulation) throw new ArgumentNullException(nameof(simulation)); } + simulation.BeforeSetup += (obj, args) => + { + foreach (var action in BeforeExecute) + { + action(simulation); + } + }; + SimulationUpdates.Apply(simulation); EntityUpdates.Apply(simulation); } @@ -96,6 +108,11 @@ public void ExecuteTemperatureBehaviorBeforeLoad(Entity entity) }); } + public void ExecuteActionBeforeSetup(Action action) + { + BeforeExecute.Add(action); + } + public void SetParameter(Entity @object, string paramName, string expression, bool beforeTemperature, bool onload) { if (@object == null) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs index 314e68cd..4356bc56 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs @@ -87,9 +87,9 @@ public void Apply(BaseSimulation simulation) { foreach (var entity in CommonUpdates.Keys) { - var beforeLoads = CommonUpdates[entity].ParameterUpdatesBeforeTemperature; + var beforeTemperature = CommonUpdates[entity].ParameterUpdatesBeforeTemperature; - foreach (var entityUpdate in beforeLoads) + foreach (var entityUpdate in beforeTemperature) { var parameter = GetEntitySimulationParameter(entityUpdate.ParameterName, entity, simulation, StringComparerProvider.Get(IsParameterNameCaseSensitive)); @@ -108,9 +108,9 @@ public void Apply(BaseSimulation simulation) { foreach (var entityPair in SimulationSpecificUpdates[simulation]) { - var beforeLoads = entityPair.Value.ParameterUpdatesBeforeTemperature; + var beforeTemperature = entityPair.Value.ParameterUpdatesBeforeTemperature; - foreach (var entityUpdate in beforeLoads) + foreach (var entityUpdate in beforeTemperature) { var parameter = GetEntitySimulationParameter(entityUpdate.ParameterName, entityPair.Key, simulation, StringComparerProvider.Get(IsParameterNameCaseSensitive)); diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Export/OrdinaryExportFunction.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Export/OrdinaryExportFunction.cs index 7319aa01..6c09848e 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Export/OrdinaryExportFunction.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Export/OrdinaryExportFunction.cs @@ -87,4 +87,4 @@ public override double Logic(string image, string[] args, IEvaluator evaluator, } } } -} +} \ No newline at end of file diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Math/PosFunction.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Math/PosFunction.cs new file mode 100644 index 00000000..9a09422a --- /dev/null +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/Math/PosFunction.cs @@ -0,0 +1,26 @@ +using SpiceSharpParser.Common.Evaluation; +using System; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Evaluation.Functions.Math +{ + public class PosFunction : Function + { + public PosFunction() + { + Name = "pos"; + ArgumentsCount = 2; + } + + public override double Logic(string image, double[] args, IEvaluator evaluator, ExpressionContext context) + { + if (args.Length != 2) + { + throw new ArgumentException("pos() function expects two arguments"); + } + + double x = args[0]; + double y = args[1]; + return x <= 0 ? y : x; + } + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/MathFunctions.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/MathFunctions.cs index 5fd26295..c5283d83 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/MathFunctions.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/Functions/MathFunctions.cs @@ -6,6 +6,17 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Evaluation.Functions { public class MathFunctions { + /// + /// Get a pos() function. + /// + /// + /// A new instance of poly function. + /// + public static IFunction CreatePos() + { + return new PosFunction(); + } + /// /// Get a poly() function. /// diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/SpiceExpressionContext.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/SpiceExpressionContext.cs index 1ce3f0ad..a2851bf1 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/SpiceExpressionContext.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Evaluation/SpiceExpressionContext.cs @@ -37,6 +37,7 @@ private void CreateSpiceFunctions() { var functions = new List { + MathFunctions.CreatePos(), MathFunctions.CreatePowInfix(Mode), MathFunctions.CreateAbs(), RandomFunctions.CreateAGauss(), diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/Export.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/Export.cs index 0192f522..a7674aee 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/Export.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/Export.cs @@ -15,7 +15,7 @@ public abstract class Export /// public Export(Simulation simulation) { - Simulation = simulation ?? throw new System.ArgumentNullException(nameof(simulation)); + Simulation = simulation; } public Simulation Simulation { get; } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs index acf2d652..93aface1 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs @@ -3,6 +3,7 @@ using SpiceSharp.Simulations; using SpiceSharpParser.Common; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Names; using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; using SpiceSharpParser.Models.Netlist.Spice.Objects; @@ -14,6 +15,10 @@ namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters /// public class PropertyExporter : Exporter { + public PropertyExporter() + { + + } /// /// Gets supported property exports. /// @@ -68,14 +73,28 @@ public override Export CreateExport(string name, string type, ParameterCollectio string modelName = modelNameGenerator.Generate(entityName); if (result.FindObject(modelName, out var model) && model is SpiceSharp.Components.Model) { - return new PropertyExport(name, simulation, modelName, parameters[1].Image, comparer); + if (simulation != null) + { + return new PropertyExport(name, simulation, modelName, parameters[1].Image, comparer); + } + else + { + return new ZeroExport(); + } } else { string componentName = componentNameGenerator.Generate(entityName); if (result.FindObject(componentName, out var component) && component is SpiceSharp.Components.Component) { - return new PropertyExport(name, simulation, componentName, parameters[1].Image, comparer); + if (simulation != null) + { + return new PropertyExport(name, simulation, componentName, parameters[1].Image, comparer); + } + else + { + return new ZeroExport(); + } } else { @@ -87,8 +106,9 @@ public override Export CreateExport(string name, string type, ParameterCollectio { if (obj2 is SpiceSharp.Components.Model) { - string modelName2 = modelNameGenerator.Generate(entityName); - return new PropertyExport(name, simulation, modelName2, parameters[1].Image, comparer); + string modelName2 = modelNameGenerator.Generate(entityName) + "_" + simulation.Name; + return new PropertyExport(name, simulation, modelName2, parameters[1].Image, + comparer); } } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExporter.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExporter.cs index 8b57789b..ad0f07e6 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExporter.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/VoltageExporter.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using SpiceSharp.Simulations; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Names; using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters.VoltageExports; diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/ZeroExport.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/ZeroExport.cs new file mode 100644 index 00000000..2b750301 --- /dev/null +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/ZeroExport.cs @@ -0,0 +1,19 @@ +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters +{ + public class ZeroExport : Export + { + public ZeroExport() + : base(null) + { + } + + public override string TypeName { get; } + + public override string QuantityUnit { get; } + + public override double Extract() + { + return 0; + } + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/PlotControl.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/PlotControl.cs index a66be795..538a8afc 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/PlotControl.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/PlotControl.cs @@ -1,200 +1,200 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using SpiceSharp.Simulations; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; -using SpiceSharpParser.Models.Netlist.Spice.Objects; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls -{ - /// - /// Reads .PLOT from SPICE netlist object model. - /// - public class PlotControl : ExportControl - { - /// - /// Initializes a new instance of the class. - /// - /// The exporter mapper. - /// The export factory. - public PlotControl( - IMapper mapper, - IExportFactory exportFactory) - : base(mapper, exportFactory) - { - } - - protected ICollection SupportedPlotTypes { get; } = new List() { "dc", "ac", "tran" }; - - /// - /// Reads statement and modifies the context. - /// - /// A statement to process. - /// A reading context. - public override void Read(Control statement, IReadingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (statement == null) - { - throw new ArgumentNullException(nameof(statement)); - } - - string type = statement.Parameters.Count > 0 ? statement.Parameters[0].Image.ToLower() : null; - string plotImage = statement.Name + ":" + statement.Parameters.ToString(); - bool merge = statement.Parameters.Any(p => p.Image == "merge"); - - if (merge) - { - if (type != null && SupportedPlotTypes.Contains(type)) - { - CreatePlot(plotImage, statement.Parameters.Skip(1), context, FilterSimulations(context.Result.Simulations, type), true); - } - else - { - CreatePlot(plotImage, statement.Parameters, context, context.Result.Simulations, false); - } - } - else - { - if (type != null && SupportedPlotTypes.Contains(type)) - { - foreach (var simulation in FilterSimulations(context.Result.Simulations, type)) - { - CreatePlot(plotImage, statement.Parameters.Skip(1), context, simulation, true); - } - } - else - { - foreach (var simulation in context.Result.Simulations) - { - if (simulation is OP) continue; - - CreatePlot(plotImage, statement.Parameters, context, simulation, false); - } - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using SpiceSharp.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; +using SpiceSharpParser.Models.Netlist.Spice.Objects; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls +{ + /// + /// Reads .PLOT from SPICE netlist object model. + /// + public class PlotControl : ExportControl + { + /// + /// Initializes a new instance of the class. + /// + /// The exporter mapper. + /// The export factory. + public PlotControl( + IMapper mapper, + IExportFactory exportFactory) + : base(mapper, exportFactory) + { + } + + protected ICollection SupportedPlotTypes { get; } = new List() { "dc", "ac", "tran" }; + + /// + /// Reads statement and modifies the context. + /// + /// A statement to process. + /// A reading context. + public override void Read(Control statement, IReadingContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (statement == null) + { + throw new ArgumentNullException(nameof(statement)); + } + + string type = statement.Parameters.Count > 0 ? statement.Parameters[0].Image.ToLower() : null; + string plotImage = statement.Name + ":" + statement.Parameters.ToString(); + bool merge = statement.Parameters.Any(p => p.Image == "merge"); + + if (merge) + { + if (type != null && SupportedPlotTypes.Contains(type)) + { + CreatePlot(plotImage, statement.Parameters.Skip(1), context, FilterSimulations(context.Result.Simulations, type), true); + } + else + { + CreatePlot(plotImage, statement.Parameters, context, context.Result.Simulations, false); + } + } + else + { + if (type != null && SupportedPlotTypes.Contains(type)) + { + foreach (var simulation in FilterSimulations(context.Result.Simulations, type)) + { + CreatePlot(plotImage, statement.Parameters.Skip(1), context, simulation, true); + } + } + else + { + foreach (var simulation in context.Result.Simulations) + { + if (simulation is OP) continue; + + CreatePlot(plotImage, statement.Parameters, context, simulation, false); + } + } + } + } + + private IEnumerable FilterSimulations(IEnumerable simulations, string type) + { + var typeLowered = type.ToLower(); + + foreach (var simulation in simulations) + { + if ((simulation is DC && typeLowered == "dc") + || (simulation is Transient && typeLowered == "tran") + || (simulation is AC && typeLowered == "ac")) + { + yield return simulation; + } + } + } + + private void CreatePlot(string plotImage, ParameterCollection parameters, IReadingContext context, Simulation simulation, bool filterSpecified) + { + var plot = new XyPlot(simulation.Name); + List exports = GenerateExports(parameters, simulation, context); + + for (int i = 0; i < exports.Count; i++) + { + Export export = exports[i]; + plot.Series.Add(new Series(export.Name)); + } + + simulation.ExportSimulationData += (sender, args) => CreatePointForSeries(simulation, args, exports, plot.Series, plot); + simulation.AfterExecute += (sender, args) => AddPlotToResultIfValid(plotImage, context, plot, simulation, filterSpecified); } - private IEnumerable FilterSimulations(IEnumerable simulations, string type) - { - var typeLowered = type.ToLower(); - - foreach (var simulation in simulations) - { - if ((simulation is DC && typeLowered == "dc") - || (simulation is Transient && typeLowered == "tran") - || (simulation is AC && typeLowered == "ac")) - { - yield return simulation; - } - } - } - - private void CreatePlot(string plotImage, ParameterCollection parameters, IReadingContext context, Simulation simulation, bool filterSpecified) - { - var plot = new XyPlot(simulation.Name); - List exports = GenerateExports(parameters, simulation, context); - - for (int i = 0; i < exports.Count; i++) - { - Export export = exports[i]; - plot.Series.Add(new Series(export.Name)); - } - - simulation.ExportSimulationData += (sender, args) => CreatePointForSeries(simulation, args, exports, plot.Series, plot); - simulation.AfterExecute += (sender, args) => AddPlotToResultIfValid(plotImage, context, plot, simulation, filterSpecified); - } - - private void CreatePlot(string plotImage, ParameterCollection parameters, IReadingContext context, IEnumerable simulations, bool filterSpecified) - { - var plot = new XyPlot($"Merged: {plotImage}"); - foreach (var simulation in simulations) - { - List exports = GenerateExports(parameters, simulation, context); - - List series = new List(); - for (int i = 0; i < exports.Count; i++) - { - Export export = exports[i]; - series.Add(new Series($"{simulation.Name} {export.Name}")); - } - plot.Series.AddRange(series); - - simulation.ExportSimulationData += (sender, args) => CreatePointForSeries(simulation, args, exports, series, plot); - } - - context.Result.AddPlot(plot); - } - - private void AddPlotToResultIfValid(string plotImage, IReadingContext context, XyPlot plot, Simulation simulation, bool filterSpecified) - { - for (int i = plot.Series.Count - 1; i >= 0; i--) - { - Series series = plot.Series[i]; - if (series.Points.Count == 0) - { - plot.Series.RemoveAt(i); - } - } - - if (plot.Series.Count > 0) - { - context.Result.AddPlot(plot); - } - else - { - context.Result.AddWarning($"{plotImage} is not valid for: {simulation.Name}"); - } - } - - private void CreatePointForSeries(Simulation simulation, ExportDataEventArgs eventArgs, List exports, List series, XyPlot plot) - { - double x = 0; - - if (simulation is Transient) - { - x = eventArgs.Time; - } - - if (simulation is AC) - { - x = eventArgs.Frequency; - } - - if (simulation is DC dc) - { - if (dc.Sweeps.Count > 1) - { - // TODO: Add support for DC Sweeps > 1 - throw new GeneralReaderException(".print doesn't support sweep count > 1"); - } - - x = eventArgs.SweepValue; - } - - for (var i = 0; i < exports.Count; i++) - { - try - { - double val = exports[i].Extract(); - if (!double.IsNaN(val)) - { - series[i].Points.Add(new Point() { X = x, Y = val }); - } - } - catch (Exception ex) - { - } - } - } - } -} + private void CreatePlot(string plotImage, ParameterCollection parameters, IReadingContext context, IEnumerable simulations, bool filterSpecified) + { + var plot = new XyPlot($"Merged: {plotImage}"); + foreach (var simulation in simulations) + { + List exports = GenerateExports(parameters, simulation, context); + + List series = new List(); + for (int i = 0; i < exports.Count; i++) + { + Export export = exports[i]; + series.Add(new Series($"{simulation.Name} {export.Name}")); + } + plot.Series.AddRange(series); + + simulation.ExportSimulationData += (sender, args) => CreatePointForSeries(simulation, args, exports, series, plot); + } + + context.Result.AddPlot(plot); + } + + private void AddPlotToResultIfValid(string plotImage, IReadingContext context, XyPlot plot, Simulation simulation, bool filterSpecified) + { + for (int i = plot.Series.Count - 1; i >= 0; i--) + { + Series series = plot.Series[i]; + if (series.Points.Count == 0) + { + plot.Series.RemoveAt(i); + } + } + + if (plot.Series.Count > 0) + { + context.Result.AddPlot(plot); + } + else + { + context.Result.AddWarning($"{plotImage} is not valid for: {simulation.Name}"); + } + } + + private void CreatePointForSeries(Simulation simulation, ExportDataEventArgs eventArgs, List exports, List series, XyPlot plot) + { + double x = 0; + + if (simulation is Transient) + { + x = eventArgs.Time; + } + + if (simulation is AC) + { + x = eventArgs.Frequency; + } + + if (simulation is DC dc) + { + if (dc.Sweeps.Count > 1) + { + // TODO: Add support for DC Sweeps > 1 + throw new GeneralReaderException(".print doesn't support sweep count > 1"); + } + + x = eventArgs.SweepValue; + } + + for (var i = 0; i < exports.Count; i++) + { + try + { + double val = exports[i].Extract(); + if (!double.IsNaN(val)) + { + series[i].Points.Add(new Point() { X = x, Y = val }); + } + } + catch (Exception ex) + { + } + } + } + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs index d4e41db8..71ec511f 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Decorators/EnableStochasticModelsSimulationDecorator.cs @@ -30,7 +30,7 @@ public BaseSimulation Decorate(BaseSimulation simulation) { simulation.BeforeExecute += (object sender, BeforeExecuteEventArgs arg) => { - foreach (var stochasticModels in modelsRegistry.GetStochasticModels()) + foreach (var stochasticModels in modelsRegistry.GetStochasticModels(simulation)) { var baseModel = stochasticModels.Key; var componentModels = stochasticModels.Value; @@ -75,6 +75,7 @@ private void SetModelLotModelParameters(BaseSimulation sim, Entity baseModel, En var currentValue = currentValueParameter.Value; var percentValue = evaluator.EvaluateValueExpression(parameterPercent.Tolerance.Image, expressionContext); double newValue = GetValueForLotParameter(expressionContext, baseModel, parameterName, currentValue, percentValue, parameterPercent.RandomDistributionName, comparer); + _context.SimulationPreparations.SetParameter(componentModel, sim, parameterName, newValue, true, false); } } @@ -99,6 +100,7 @@ private void SetModelDevModelParameters(BaseSimulation sim, Entity baseModel, En var percentValue = evaluator.EvaluateValueExpression(parameterPercent.Tolerance.Image, expressionContext); double newValue = GetValueForDevParameter(expressionContext, currentValue, percentValue, parameterPercent.RandomDistributionName); + _context.SimulationPreparations.SetParameter(componentModel, sim, parameterName, newValue, true, false); } } @@ -108,7 +110,7 @@ private double GetValueForDevParameter(ExpressionContext expressionContext, doub { var random = expressionContext.Randomizer.GetRandomProvider(expressionContext.Seed, distributionName); var r = random.NextSignedDouble(); - return currentValue + (percentValue / 100.0 * currentValue * r); + return currentValue + (percentValue / 100.0) * currentValue * r; } private double GetValueForLotParameter(ExpressionContext expressionContext, Entity baseModel, string parameterName, double currentValue, double percentValue, string distributionName, IEqualityComparer comparer) @@ -119,7 +121,7 @@ private double GetValueForLotParameter(ExpressionContext expressionContext, Enti } var random = expressionContext.Randomizer.GetRandomProvider(expressionContext.Seed, distributionName); - double newValue = currentValue + (percentValue / 100.0 * currentValue * random.NextSignedDouble()); + double newValue = currentValue + (percentValue / 100.0) * currentValue * random.NextSignedDouble(); if (!LotValues.ContainsKey(baseModel)) { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs index 4a68bb3e..05d3fb3e 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Factories/CreateSimulationsForMonteCarloFactory.cs @@ -1,98 +1,98 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using SpiceSharp.Simulations; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.Models.Netlist.Spice.Objects; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Factories -{ - public class CreateSimulationsForMonteCarloFactory : ICreateSimulationsForMonteCarloFactory - { - public CreateSimulationsForMonteCarloFactory( - ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory temperatureAndParameterSweepsSimulationFactory, - IExportFactory exportFactory, - IMapper mapperExporter) - { - TemperatureAndParameterSweepsSimulationFactory = temperatureAndParameterSweepsSimulationFactory; - ExportFactory = exportFactory; - MapperExporter = mapperExporter; - } - +using System; +using System.Collections.Generic; +using System.Linq; +using SpiceSharp.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Common; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.Models.Netlist.Spice.Objects; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Factories +{ + public class CreateSimulationsForMonteCarloFactory : ICreateSimulationsForMonteCarloFactory + { + public CreateSimulationsForMonteCarloFactory( + ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory temperatureAndParameterSweepsSimulationFactory, + IExportFactory exportFactory, + IMapper mapperExporter) + { + TemperatureAndParameterSweepsSimulationFactory = temperatureAndParameterSweepsSimulationFactory; + ExportFactory = exportFactory; + MapperExporter = mapperExporter; + } + /// /// Gets the exporter mapper. - /// - protected IMapper MapperExporter { get; } - + /// + protected IMapper MapperExporter { get; } + /// /// Gets the simulations factory. - /// - protected ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory TemperatureAndParameterSweepsSimulationFactory { get; } - + /// + protected ICreateSimulationsForAllParameterSweepsAndTemperaturesFactory TemperatureAndParameterSweepsSimulationFactory { get; } + /// /// Gets the export factory. - /// - protected IExportFactory ExportFactory { get; } - + /// + protected IExportFactory ExportFactory { get; } + /// /// Creates simulations for Monte Carlo simulation. /// /// Statement/ /// Context. /// Simulation factory. - /// - public List Create(Control statement, IReadingContext context, Func createSimulation) - { - context.Result.MonteCarlo.Enabled = true; - context.Result.MonteCarlo.Seed = context.Result.SimulationConfiguration.MonteCarloConfiguration.Seed; - context.Result.MonteCarlo.OutputVariable = context.Result.SimulationConfiguration.MonteCarloConfiguration.OutputVariable.Image; - context.Result.MonteCarlo.Function = context.Result.SimulationConfiguration.MonteCarloConfiguration.Function; - - var result = new List(); - - for (var i = 0; i < context.Result.SimulationConfiguration.MonteCarloConfiguration.Runs; i++) - { - var simulations = TemperatureAndParameterSweepsSimulationFactory.CreateSimulations(statement, context, createSimulation); - AttachMonteCarloDataGathering(context, simulations); - result.AddRange(simulations); - } - - return result; - } - - protected void AttachMonteCarloDataGathering(IReadingContext context, IEnumerable simulations) - { - foreach (var simulation in simulations) - { - AttachMonteCarloDataGatheringForSimulation(context, simulation); - } - } - - protected void AttachMonteCarloDataGatheringForSimulation(IReadingContext context, BaseSimulation simulation) - { - var exportParam = context.Result.SimulationConfiguration.MonteCarloConfiguration.OutputVariable; - - simulation.BeforeSetup += (sender, args) => - { - Export export = context.Result.Exports.FirstOrDefault(e => e.Simulation == simulation && e.Name == exportParam.Image); - - if (export == null) - { - export = ExportFactory.Create(exportParam, context, simulation, MapperExporter); - } - - simulation.ExportSimulationData += (exportSender, exportArgs) => - { - if (export != null) - { - var value = export.Extract(); - context.Result.MonteCarlo.Collect(simulation, value); - } - }; - }; - } - } -} + /// + public List Create(Control statement, IReadingContext context, Func createSimulation) + { + context.Result.MonteCarlo.Enabled = true; + context.Result.MonteCarlo.Seed = context.Result.SimulationConfiguration.MonteCarloConfiguration.Seed; + context.Result.MonteCarlo.OutputVariable = context.Result.SimulationConfiguration.MonteCarloConfiguration.OutputVariable.Image; + context.Result.MonteCarlo.Function = context.Result.SimulationConfiguration.MonteCarloConfiguration.Function; + + var result = new List(); + + for (var i = 0; i < context.Result.SimulationConfiguration.MonteCarloConfiguration.Runs; i++) + { + var simulations = TemperatureAndParameterSweepsSimulationFactory.CreateSimulations(statement, context, createSimulation); + AttachMonteCarloDataGathering(context, simulations); + result.AddRange(simulations); + } + + return result; + } + + protected void AttachMonteCarloDataGathering(IReadingContext context, IEnumerable simulations) + { + foreach (var simulation in simulations) + { + AttachMonteCarloDataGatheringForSimulation(context, simulation); + } + } + + protected void AttachMonteCarloDataGatheringForSimulation(IReadingContext context, BaseSimulation simulation) + { + var exportParam = context.Result.SimulationConfiguration.MonteCarloConfiguration.OutputVariable; + + simulation.BeforeSetup += (sender, args) => + { + Export export = context.Result.Exports.FirstOrDefault(e => e.Simulation == simulation && e.Name == exportParam.Image); + + if (export == null) + { + export = ExportFactory.Create(exportParam, context, simulation, MapperExporter); + } + + simulation.ExportSimulationData += (exportSender, exportArgs) => + { + if (export != null) + { + var value = export.Extract(); + context.Result.MonteCarlo.Collect(simulation, value); + } + }; + }; + } + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/MonteCarloResult.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/MonteCarloResult.cs index 9cf232b3..b11df173 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/MonteCarloResult.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/MonteCarloResult.cs @@ -125,6 +125,8 @@ protected HistogramPlot CreatePlot(string title, int bins, List values) { var max = values.Max(); var min = values.Min(); + var width = max - min; + var binWidth = (max - min) / bins; if (Math.Abs(binWidth) < 1e-16) { @@ -142,16 +144,12 @@ protected HistogramPlot CreatePlot(string title, int bins, List values) foreach (var value in values) { - int binIndex = 0; + int binIndex = binWidth != 0 ? (int)Math.Floor((value - min) / binWidth) + 1 : bins; - if (value == max) + if (binIndex > bins) { binIndex = bins; } - else - { - binIndex = binWidth != 0 ? (int)Math.Floor((value - min) / binWidth) + 1 : bins; - } plot.Bins[binIndex].Count += 1; } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs index cf65af1a..138fd206 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs @@ -126,12 +126,16 @@ protected SpiceSharp.Components.Component GenerateCap(string name, ParameterColl } else { - context.ModelsRegistry.SetModel( - capacitor, - parameters.GetString(2), - $"Could not find model {parameters.GetString(2)} for capacitor {name}", - (CapacitorModel model) => capacitor.Model = model.Name, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + capacitor, + simulation, + parameters.GetString(2), + $"Could not find model {parameters.GetString(2)} for capacitor {name}", + (CapacitorModel model) => capacitor.Model = model.Name, + context.Result); + }); modelBased = true; } @@ -317,12 +321,17 @@ protected SpiceSharp.Components.Component GenerateRes(string name, ParameterColl var modelName = resistorParameters[0].Image; // Ignore tc parameter on resistor ... - context.ModelsRegistry.SetModel( - res, - modelName, - $"Could not find model {modelName} for resistor {name}", - (ResistorModel model) => res.Model = model.Name, - context.Result); + + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + res, + simulation, + modelName, + $"Could not find model {modelName} for resistor {name}", + (ResistorModel model) => res.Model = model.Name, + context.Result); + }); resistorParameters.RemoveAt(0); diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/BipolarJunctionTransistorGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/BipolarJunctionTransistorGenerator.cs index 8ed1edb0..febdfae2 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/BipolarJunctionTransistorGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/BipolarJunctionTransistorGenerator.cs @@ -42,12 +42,16 @@ public SpiceSharp.Components.Component Generate(string componentIdentifier, stri throw new WrongParametersCountException(); } - context.ModelsRegistry.SetModel( - bjt, - parameters.GetString(4), - $"Could not find model {parameters.GetString(4)} for BJT {originalName}", - (BipolarJunctionTransistorModel model) => bjt.Model = model.Name, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + bjt, + simulation, + parameters.GetString(4), + $"Could not find model {parameters.GetString(4)} for BJT {originalName}", + (BipolarJunctionTransistorModel model) => bjt.Model = model.Name, + context.Result); + }); for (int i = 5; i < parameters.Count; i++) { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/DiodeGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/DiodeGenerator.cs index 04cdeed6..fdf7d45f 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/DiodeGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/DiodeGenerator.cs @@ -27,12 +27,16 @@ public SpiceSharp.Components.Component Generate(string componentIdentifier, stri Diode diode = new Diode(componentIdentifier); context.CreateNodes(diode, parameters); - context.ModelsRegistry.SetModel( - diode, - parameters.GetString(2), - $"Could not find model {parameters.GetString(2)} for diode {originalName}", - (DiodeModel model) => diode.Model = model.Name, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + diode, + simulation, + parameters.GetString(2), + $"Could not find model {parameters.GetString(2)} for diode {originalName}", + (DiodeModel model) => diode.Model = model.Name, + context.Result); + }); // Read the rest of the parameters for (int i = 3; i < parameters.Count; i++) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/JFETGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/JFETGenerator.cs index 2df4ce95..85e3ec60 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/JFETGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/JFETGenerator.cs @@ -21,12 +21,16 @@ public SpiceSharp.Components.Component Generate(string componentIdentifier, stri JFET jfet = new JFET(componentIdentifier); context.CreateNodes(jfet, parameters); - context.ModelsRegistry.SetModel( - jfet, - parameters.GetString(3), - $"Could not find model {parameters.GetString(3)} for JFET {originalName}", - (JFETModel model) => jfet.Model = model.Name, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + jfet, + simulation, + parameters.GetString(3), + $"Could not find model {parameters.GetString(3)} for JFET {originalName}", + (JFETModel model) => jfet.Model = model.Name, + context.Result); + }); // Read the rest of the parameters for (int i = 3; i < parameters.Count; i++) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs index a7891a2c..cd394ed9 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs @@ -75,12 +75,16 @@ public override SpiceSharp.Components.Component Generate(string componentIdentif var mosfetDetails = Mosfets[model.GetType()].Invoke(componentIdentifier); mosfet = mosfetDetails.Mosfet; - context.ModelsRegistry.SetModel( - mosfetDetails.Mosfet, - modelName, - $"Could not find model {modelName} for mosfet {componentIdentifier}", - mosfetDetails.SetModelAction, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + mosfetDetails.Mosfet, + simulation, + modelName, + $"Could not find model {modelName} for mosfet {componentIdentifier}", + mosfetDetails.SetModelAction, + context.Result); + }); } else { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs index 2f148aa6..6f1b0383 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs @@ -3,10 +3,12 @@ using System.Globalization; using SpiceSharp.Components; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; using SpiceSharpParser.ModelReaders.Netlist.Spice.Custom; using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; using SpiceSharpParser.Models.Netlist.Spice.Objects; using SpiceSharpParser.Models.Netlist.Spice.Objects.Parameters; +using Model = SpiceSharp.Components.Model; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.EntityGenerators.Components { @@ -49,20 +51,34 @@ protected SpiceSharp.Components.Component GenerateVoltageSwitch(string name, Par string modelName = parameters.GetString(4); - if (context.ModelsRegistry.FindModel(modelName) is VSwitchModel s) + if (context.ModelsRegistry.FindModel(modelName) is VSwitchModel vmodel) { Resistor resistor = new Resistor(name); + Model resistorModel = vmodel; context.CreateNodes(resistor, parameters.Take(2)); context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor); - double rOn = s.ParameterSets.GetParameter("ron"); - double rOff = s.ParameterSets.GetParameter("roff"); - double vOn = s.ParameterSets.GetParameter("von"); - double vOff = s.ParameterSets.GetParameter("voff"); - - string resExpression = $"table(v({parameters.GetString(2)}, {parameters.GetString(3)}), {vOff.ToString(CultureInfo.InvariantCulture)}, {rOff.ToString(CultureInfo.InvariantCulture)}, {vOn.ToString(CultureInfo.InvariantCulture)}, {rOn.ToString(CultureInfo.InvariantCulture)})"; - context.SetParameter(resistor, "resistance", resExpression); + context.SimulationPreparations.ExecuteActionBeforeSetup( + (simulation) => + { + if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry) + { + resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, vmodel); + + if (resistorModel != vmodel) + { + stochasticModelsRegistry.RegisterModelInstance(resistorModel); + context.Result.Circuit.Add(resistorModel); + } + } + + double rOff = resistorModel.ParameterSets.GetParameter("roff"); + + string resExpression = + $"pos(table(v({parameters.GetString(2)}, {parameters.GetString(3)}), @{resistorModel.Name}[voff], @{resistorModel.Name}[roff] , @{resistorModel.Name}[von], @{resistorModel.Name}[ron]), {rOff.ToString(CultureInfo.InvariantCulture)})"; + context.SetParameter(resistor, "resistance", resExpression, onload: true, beforeTemperature: true); + }); return resistor; } else @@ -70,12 +86,16 @@ protected SpiceSharp.Components.Component GenerateVoltageSwitch(string name, Par VoltageSwitch vsw = new VoltageSwitch(name); context.CreateNodes(vsw, parameters); - context.ModelsRegistry.SetModel( - vsw, - parameters.GetString(4), - $"Could not find model {parameters.GetString(4)} for voltage switch {name}", - (VoltageSwitchModel model) => { vsw.Model = model.Name; }, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + vsw, + simulation, + parameters.GetString(4), + $"Could not find model {parameters.GetString(4)} for voltage switch {name}", + (VoltageSwitchModel model) => { vsw.Model = model.Name; }, + context.Result); + }); // Optional ON or OFF if (parameters.Count == 6) @@ -148,15 +168,19 @@ protected SpiceSharp.Components.Component GenerateCurrentSwitch(string name, Par else { throw new WrongParameterTypeException("Voltage source name expected"); - } - + } + // Get the model - context.ModelsRegistry.SetModel( - csw, - parameters.GetString(3), - $"Could not find model {parameters.GetString(3)} for current switch {name}", - (CurrentSwitchModel model) => csw.Model = model.Name, - context.Result); + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + csw, + simulation, + parameters.GetString(3), + $"Could not find model {parameters.GetString(3)} for current switch {name}", + (CurrentSwitchModel model) => csw.Model = model.Name, + context.Result); + }); // Optional on or off if (parameters.Count > 4) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs index a2e86803..ffaa7817 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs @@ -62,7 +62,7 @@ public SpiceSharp.Components.Model GenerateModel(IModelGenerator modelGenerator, } var filteredParameters = FilterDevAndLot(parameters); - var model = modelGenerator.Generate(id, type, parameters, context); + var model = modelGenerator.Generate(id, type, filteredParameters, context); if (model == null) { throw new GeneralReaderException("Couldn't generate model"); diff --git a/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs b/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs index 3f9c5fc5..2ef3fab7 100644 --- a/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs +++ b/src/SpiceSharpParser/Parsers/Expression/SpiceExpressionParser.cs @@ -616,7 +616,7 @@ private void EvaluateFunction(string expression, FunctionOperator op, int? endIn if (endIndex != null) { return stringFunction.Logic( - op.Name + expression.Substring(op.StartIndex - 1, endIndex.Value - op.StartIndex + 2), + op.Name + expression.Substring(op.StartIndex, endIndex.Value - op.StartIndex + 1), args, evalContext.Evaluator, evalContext.ExpressionContext); From 44fbf20854fffd7380b23b7668928a08af089060 Mon Sep 17 00:00:00 2001 From: Marcin Date: Tue, 23 Jul 2019 22:01:38 +0200 Subject: [PATCH 3/6] Voltage and current switch fixes --- .../Netlist/Spice/Context/IReadingContext.cs | 336 +++++++------- .../Netlist/Spice/Context/ReadingContext.cs | 2 +- .../Spice/Context/Updates/EntityUpdates.cs | 22 +- .../Controls/Exporters/PropertyExporter.cs | 14 +- .../Components/ComponentGenerator.cs | 2 +- .../Components/RLCKGenerator.cs | 10 +- .../Components/SwitchGenerator.cs | 417 +++++++++--------- 7 files changed, 420 insertions(+), 383 deletions(-) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs index 7334fdb1..ff80ae38 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IReadingContext.cs @@ -1,170 +1,170 @@ -using System.Collections.Generic; -using SpiceSharp.Circuits; -using SpiceSharpParser.Common.Evaluation; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Names; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.Models.Netlist.Spice.Objects; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context -{ - public interface IReadingContext - { - /// - /// Gets the context name. - /// - string Name { get; } - - SimulationExpressionContexts SimulationExpressionContexts { get; } - +using System.Collections.Generic; +using SpiceSharp.Circuits; +using SpiceSharpParser.Common.Evaluation; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Names; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Mappings; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.Models.Netlist.Spice.Objects; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context +{ + public interface IReadingContext + { + /// + /// Gets the context name. + /// + string Name { get; } + + SimulationExpressionContexts SimulationExpressionContexts { get; } + /// /// Gets the reading expression context. - /// - ExpressionContext ReadingExpressionContext { get; } - - /// - /// Gets the simulation parameters. - /// - ISimulationPreparations SimulationPreparations { get; } - - /// - /// Gets the simulation evaluators. - /// - ISimulationEvaluators SimulationEvaluators { get; } - - /// - /// Gets the reading evaluator. - /// - IEvaluator ReadingEvaluator { get; } - - /// - /// Gets the parent of the context. - /// - IReadingContext Parent { get; } - - /// - /// Gets exporter mapper. - /// - IMapper Exporters { get; } - - /// - /// Gets the children of the reading context. - /// - ICollection Children { get; } - - /// - /// Gets the list of available subcircuit for the context. - /// - ICollection AvailableSubcircuits { get; } - - /// - /// Gets the result service for the context. - /// - IResultService Result { get; } - - /// - /// Gets the node name generator. - /// - INodeNameGenerator NodeNameGenerator { get; } - - /// - /// Gets the component name generator. - /// - IObjectNameGenerator ComponentNameGenerator { get; } - - /// - /// Gets the model name generator. - /// - IObjectNameGenerator ModelNameGenerator { get; } - - /// - /// Gets the stochastic models registry. - /// - IModelsRegistry ModelsRegistry { get; } - - /// - /// Gets or sets the statements reader. - /// - ISpiceStatementsReader StatementsReader { get; set; } - - /// - /// Gets or sets the waveform reader. - /// - IWaveformReader WaveformReader { get; set; } - - /// - /// Gets or sets case-sensitivity settings. - /// - SpiceNetlistCaseSensitivitySettings CaseSensitivity { get; set; } - - /// - /// Gets the expression parser. - /// - IExpressionParser ExpressionParser { get; } - - /// - /// Gets or sets working directory. - /// - string WorkingDirectory { get; } - - /// - /// Parses an expression to double. - /// - /// Expression to parse - /// - /// A value of expression. - /// - double EvaluateDouble(string expression); - - /// - /// Sets a parameter. - /// - /// Parameter name. - /// Parameter value. - void SetParameter(string parameterName, double value); - - /// - /// Sets a parameter. - /// - /// Parameter name. - /// Parameter value expression. - void SetParameter(string parameterName, string valueExpression); - - /// - /// Sets parameter of entity to value of expression. - /// - /// Entity. - /// Parameter name. - /// Value expression. - /// Should be re-evaluated OnBeforeLoad. - void SetParameter(Entity entity, string parameterName, string valueExpression, bool onload = true, - bool beforeTemperature = true); - - /// - /// Sets the initial voltage. - /// - /// Node name. - /// Node voltage expression. - void SetICVoltage(string nodeName, string expression); - - /// - /// Creates nodes for a component. - /// - /// A component - /// Parameters of component - void CreateNodes(SpiceSharp.Components.Component component, ParameterCollection parameters); - - /// - /// Reads the statements with given order. - /// - /// Statements. - /// Orderer of statements. - void Read(Statements statements, ISpiceStatementsOrderer orderer); - - void AddFunction(string functionName, List arguments, string body); - - void SetNamedExpression(string expressionName, string expression); - } -} + /// + ExpressionContext ReadingExpressionContext { get; } + + /// + /// Gets the simulation parameters. + /// + ISimulationPreparations SimulationPreparations { get; } + + /// + /// Gets the simulation evaluators. + /// + ISimulationEvaluators SimulationEvaluators { get; } + + /// + /// Gets the reading evaluator. + /// + IEvaluator ReadingEvaluator { get; } + + /// + /// Gets the parent of the context. + /// + IReadingContext Parent { get; } + + /// + /// Gets exporter mapper. + /// + IMapper Exporters { get; } + + /// + /// Gets the children of the reading context. + /// + ICollection Children { get; } + + /// + /// Gets the list of available subcircuit for the context. + /// + ICollection AvailableSubcircuits { get; } + + /// + /// Gets the result service for the context. + /// + IResultService Result { get; } + + /// + /// Gets the node name generator. + /// + INodeNameGenerator NodeNameGenerator { get; } + + /// + /// Gets the component name generator. + /// + IObjectNameGenerator ComponentNameGenerator { get; } + + /// + /// Gets the model name generator. + /// + IObjectNameGenerator ModelNameGenerator { get; } + + /// + /// Gets the stochastic models registry. + /// + IModelsRegistry ModelsRegistry { get; } + + /// + /// Gets or sets the statements reader. + /// + ISpiceStatementsReader StatementsReader { get; set; } + + /// + /// Gets or sets the waveform reader. + /// + IWaveformReader WaveformReader { get; set; } + + /// + /// Gets or sets case-sensitivity settings. + /// + SpiceNetlistCaseSensitivitySettings CaseSensitivity { get; set; } + + /// + /// Gets the expression parser. + /// + IExpressionParser ExpressionParser { get; } + + /// + /// Gets or sets working directory. + /// + string WorkingDirectory { get; } + + /// + /// Parses an expression to double. + /// + /// Expression to parse + /// + /// A value of expression. + /// + double EvaluateDouble(string expression); + + /// + /// Sets a parameter. + /// + /// Parameter name. + /// Parameter value. + void SetParameter(string parameterName, double value); + + /// + /// Sets a parameter. + /// + /// Parameter name. + /// Parameter value expression. + void SetParameter(string parameterName, string valueExpression); + + /// + /// Sets parameter of entity to value of expression. + /// + /// Entity. + /// Parameter name. + /// Value expression. + /// Should be re-evaluated before temperature. + /// Should be re-evaluated OnBeforeLoad. + void SetParameter(Entity entity, string parameterName, string valueExpression, bool beforeTemperature = true, bool onload = true); + + /// + /// Sets the initial voltage. + /// + /// Node name. + /// Node voltage expression. + void SetICVoltage(string nodeName, string expression); + + /// + /// Creates nodes for a component. + /// + /// A component + /// Parameters of component + void CreateNodes(SpiceSharp.Components.Component component, ParameterCollection parameters); + + /// + /// Reads the statements with given order. + /// + /// Statements. + /// Orderer of statements. + void Read(Statements statements, ISpiceStatementsOrderer orderer); + + void AddFunction(string functionName, List arguments, string body); + + void SetNamedExpression(string expressionName, string expression); + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs index 8fc407bd..065cd917 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ReadingContext.cs @@ -344,7 +344,7 @@ public void SetNamedExpression(string expressionName, string expression) ReadingExpressionContext.SetNamedExpression(expressionName, expression, foundParameters); } - public void SetParameter(Entity entity, string parameterName, string expression, bool onload = true, bool beforeTemperature = true) + public void SetParameter(Entity entity, string parameterName, string expression, bool beforeTemperature = true, bool onload = true) { if (entity == null) { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs index 4356bc56..9aab4a55 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Updates/EntityUpdates.cs @@ -55,7 +55,11 @@ public void Apply(BaseSimulation simulation) Common.Evaluation.ExpressionContext context = GetEntityContext(simulation, entity); var value = entityUpdate.GetValue(evaluator, context); - parameter.Value = value; + + if (!double.IsNaN(value)) + { + parameter.Value = value; + } } } } @@ -76,7 +80,10 @@ public void Apply(BaseSimulation simulation) Common.Evaluation.ExpressionContext context = GetEntityContext(simulation, entityPair.Key); var value = entityUpdate.GetValue(evaluator, context); - parameter.Value = value; + if (!double.IsNaN(value)) + { + parameter.Value = value; + } } } } @@ -99,7 +106,11 @@ public void Apply(BaseSimulation simulation) Common.Evaluation.ExpressionContext context = GetEntityContext(simulation, entity); var value = entityUpdate.GetValue(evaluator, context); - parameter.Value = value; + + if (!double.IsNaN(value)) + { + parameter.Value = value; + } } } } @@ -120,7 +131,10 @@ public void Apply(BaseSimulation simulation) Common.Evaluation.ExpressionContext context = GetEntityContext(simulation, entityPair.Key); var value = entityUpdate.GetValue(evaluator, context); - parameter.Value = value; + if (!double.IsNaN(value)) + { + parameter.Value = value; + } } } } diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs index 93aface1..b5fec280 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Exporters/PropertyExporter.cs @@ -71,7 +71,19 @@ public override Export CreateExport(string name, string type, ParameterCollectio if (result != null) { string modelName = modelNameGenerator.Generate(entityName); - if (result.FindObject(modelName, out var model) && model is SpiceSharp.Components.Model) + + if (result.FindObject(entityName, out var entity) && entity is SpiceSharp.Components.Model) + { + if (simulation != null) + { + return new PropertyExport(name, simulation, entityName, parameters[1].Image, comparer); + } + else + { + return new ZeroExport(); + } + } + else if (result.FindObject(modelName, out var model) && model is SpiceSharp.Components.Model) { if (simulation != null) { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/ComponentGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/ComponentGenerator.cs index 232f54a6..ae629be3 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/ComponentGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/ComponentGenerator.cs @@ -18,7 +18,7 @@ protected void SetParameters(IReadingContext context, Entity entity, ParameterCo { if (parameter is AssignmentParameter ap) { - context.SetParameter(entity, ap.Name, ap.Value, onload); + context.SetParameter(entity, ap.Name, ap.Value, true, onload); } else { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs index 138fd206..e535bb88 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/RLCKGenerator.cs @@ -278,11 +278,11 @@ protected SpiceSharp.Components.Component GenerateRes(string name, ParameterColl // Set resistance if (something is AssignmentParameter asp) { - context.SetParameter(res, "resistance", asp.Value, isDynamic); + context.SetParameter(res, "resistance", asp.Value, true, isDynamic); } else { - context.SetParameter(res, "resistance", something.Image, isDynamic); + context.SetParameter(res, "resistance", something.Image, true, isDynamic); } } else @@ -340,7 +340,7 @@ protected SpiceSharp.Components.Component GenerateRes(string name, ParameterColl || resistorParameters[0] is ValueParameter || resistorParameters[0] is ExpressionParameter)) { - context.SetParameter(res, "resistance", resistorParameters[0].Image, false); + context.SetParameter(res, "resistance", resistorParameters[0].Image, true); resistorParameters.RemoveAt(0); } } @@ -378,11 +378,11 @@ protected SpiceSharp.Components.Component GenerateRes(string name, ParameterColl if (resistanceParameter is AssignmentParameter asp) { - context.SetParameter(res, "resistance", asp.Value, isDynamic); + context.SetParameter(res, "resistance", asp.Value, true, isDynamic); } else { - context.SetParameter(res, "resistance", resistanceParameter.Image, isDynamic); + context.SetParameter(res, "resistance", resistanceParameter.Image, true, isDynamic); } resistorParameters.RemoveAt(0); diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs index 6f1b0383..9f443cec 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/SwitchGenerator.cs @@ -1,205 +1,216 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using SpiceSharp.Components; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Custom; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; -using SpiceSharpParser.Models.Netlist.Spice.Objects; -using SpiceSharpParser.Models.Netlist.Spice.Objects.Parameters; -using Model = SpiceSharp.Components.Model; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.EntityGenerators.Components -{ - public class SwitchGenerator : ComponentGenerator - { - /// - /// Gets generated types. - /// - /// - /// Generated types. - /// - public override IEnumerable GeneratedTypes => new List { "s", "w" }; - - public override SpiceSharp.Components.Component Generate(string componentIdentifier, string originalName, string type, ParameterCollection parameters, IReadingContext context) - { - switch (type.ToLower()) - { - case "s": return GenerateVoltageSwitch(componentIdentifier, parameters, context); - case "w": return GenerateCurrentSwitch(componentIdentifier, parameters, context); - } - - return null; - } - - /// - /// Generates a voltage switch. - /// - /// Name of voltage switch to generate. - /// Parameters for voltage switch. - /// Reading context. - /// - /// A new voltage switch. - /// - protected SpiceSharp.Components.Component GenerateVoltageSwitch(string name, ParameterCollection parameters, IReadingContext context) - { - if (parameters.Count < 5) - { - throw new WrongParametersCountException("Wrong parameter count for voltage switch"); - } - - string modelName = parameters.GetString(4); - - if (context.ModelsRegistry.FindModel(modelName) is VSwitchModel vmodel) - { - Resistor resistor = new Resistor(name); - Model resistorModel = vmodel; - context.CreateNodes(resistor, parameters.Take(2)); - context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor); - - - context.SimulationPreparations.ExecuteActionBeforeSetup( - (simulation) => - { - if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry) - { - resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, vmodel); - - if (resistorModel != vmodel) - { - stochasticModelsRegistry.RegisterModelInstance(resistorModel); - context.Result.Circuit.Add(resistorModel); - } - } - - double rOff = resistorModel.ParameterSets.GetParameter("roff"); - - string resExpression = - $"pos(table(v({parameters.GetString(2)}, {parameters.GetString(3)}), @{resistorModel.Name}[voff], @{resistorModel.Name}[roff] , @{resistorModel.Name}[von], @{resistorModel.Name}[ron]), {rOff.ToString(CultureInfo.InvariantCulture)})"; - context.SetParameter(resistor, "resistance", resExpression, onload: true, beforeTemperature: true); - }); - return resistor; - } - else - { - VoltageSwitch vsw = new VoltageSwitch(name); - context.CreateNodes(vsw, parameters); - - context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => - { - context.ModelsRegistry.SetModel( - vsw, - simulation, - parameters.GetString(4), - $"Could not find model {parameters.GetString(4)} for voltage switch {name}", - (VoltageSwitchModel model) => { vsw.Model = model.Name; }, - context.Result); - }); - - // Optional ON or OFF - if (parameters.Count == 6) - { - switch (parameters.GetString(5).ToLower()) - { - case "on": - vsw.ParameterSets.SetParameter("on"); - break; - case "off": - vsw.ParameterSets.SetParameter("off"); - break; - default: - throw new Exception("ON or OFF expected"); - } - } - else if (parameters.Count > 6) - { - throw new WrongParametersCountException("Too many parameters for voltage switch"); - } - - return vsw; - } - } - - /// - /// Generates a current switch. - /// - /// Name of current switch. - /// Parameters of current switch. - /// Reading context. - /// - /// A new instance of current switch. - /// - protected SpiceSharp.Components.Component GenerateCurrentSwitch(string name, ParameterCollection parameters, IReadingContext context) - { - if (parameters.Count < 4) - { - throw new WrongParametersCountException("Wrong parameter count for current switch"); - } - - string modelName = parameters.GetString(3); - - if (context.ModelsRegistry.FindModel(modelName) is ISwitchModel s) - { - Resistor resistor = new Resistor(name); - context.CreateNodes(resistor, parameters.Take(2)); - context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor); - - double rOn = s.ParameterSets.GetParameter("ron"); - double rOff = s.ParameterSets.GetParameter("roff"); - double iOn = s.ParameterSets.GetParameter("ion"); - double iOff = s.ParameterSets.GetParameter("ioff"); - - string resExpression = $"table(i({parameters.GetString(2)}), {iOff.ToString(CultureInfo.InvariantCulture)}, {rOff.ToString(CultureInfo.InvariantCulture)}, {iOn.ToString(CultureInfo.InvariantCulture)}, {rOn.ToString(CultureInfo.InvariantCulture)})"; - context.SetParameter(resistor, "resistance", resExpression); - - return resistor; - } - else - { - CurrentSwitch csw = new CurrentSwitch(name); - context.CreateNodes(csw, parameters); - - // Get the controlling voltage source - if (parameters[2] is WordParameter || parameters[2] is IdentifierParameter) - { - csw.ControllingName = context.ComponentNameGenerator.Generate(parameters.GetString(2)); - } - else - { - throw new WrongParameterTypeException("Voltage source name expected"); +using System; +using System.Collections.Generic; +using System.Globalization; +using SpiceSharp.Components; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Custom; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Exceptions; +using SpiceSharpParser.Models.Netlist.Spice.Objects; +using SpiceSharpParser.Models.Netlist.Spice.Objects.Parameters; +using Model = SpiceSharp.Components.Model; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.EntityGenerators.Components +{ + public class SwitchGenerator : ComponentGenerator + { + /// + /// Gets generated types. + /// + /// + /// Generated types. + /// + public override IEnumerable GeneratedTypes => new List { "s", "w" }; + + public override SpiceSharp.Components.Component Generate(string componentIdentifier, string originalName, string type, ParameterCollection parameters, IReadingContext context) + { + switch (type.ToLower()) + { + case "s": return GenerateVoltageSwitch(componentIdentifier, parameters, context); + case "w": return GenerateCurrentSwitch(componentIdentifier, parameters, context); + } + + return null; + } + + /// + /// Generates a voltage switch. + /// + /// Name of voltage switch to generate. + /// Parameters for voltage switch. + /// Reading context. + /// + /// A new voltage switch. + /// + protected SpiceSharp.Components.Component GenerateVoltageSwitch(string name, ParameterCollection parameters, IReadingContext context) + { + if (parameters.Count < 5) + { + throw new WrongParametersCountException("Wrong parameter count for voltage switch"); + } + + string modelName = parameters.GetString(4); + + if (context.ModelsRegistry.FindModel(modelName) is VSwitchModel vmodel) + { + Resistor resistor = new Resistor(name); + Model resistorModel = vmodel; + context.CreateNodes(resistor, parameters.Take(2)); + context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor); + + context.SimulationPreparations.ExecuteActionBeforeSetup( + (simulation) => + { + if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry) + { + resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, vmodel); + + if (!context.Result.FindObject(resistorModel.Name, out _)) + { + stochasticModelsRegistry.RegisterModelInstance(resistorModel); + context.Result.Circuit.Add(resistorModel); + } + } + + double rOff = resistorModel.ParameterSets.GetParameter("roff"); + + string resExpression = + $"pos(table(v({parameters.GetString(2)}, {parameters.GetString(3)}), @{resistorModel.Name}[voff], @{resistorModel.Name}[roff] , @{resistorModel.Name}[von], @{resistorModel.Name}[ron]), {rOff.ToString(CultureInfo.InvariantCulture)})"; + context.SetParameter(resistor, "resistance", resExpression, beforeTemperature: true, onload: true); + }); + return resistor; + } + else + { + VoltageSwitch vsw = new VoltageSwitch(name); + context.CreateNodes(vsw, parameters); + + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + vsw, + simulation, + parameters.GetString(4), + $"Could not find model {parameters.GetString(4)} for voltage switch {name}", + (VoltageSwitchModel model) => { vsw.Model = model.Name; }, + context.Result); + }); + + // Optional ON or OFF + if (parameters.Count == 6) + { + switch (parameters.GetString(5).ToLower()) + { + case "on": + vsw.ParameterSets.SetParameter("on"); + break; + case "off": + vsw.ParameterSets.SetParameter("off"); + break; + default: + throw new Exception("ON or OFF expected"); + } + } + else if (parameters.Count > 6) + { + throw new WrongParametersCountException("Too many parameters for voltage switch"); + } + + return vsw; + } + } + + /// + /// Generates a current switch. + /// + /// Name of current switch. + /// Parameters of current switch. + /// Reading context. + /// + /// A new instance of current switch. + /// + protected SpiceSharp.Components.Component GenerateCurrentSwitch(string name, ParameterCollection parameters, IReadingContext context) + { + if (parameters.Count < 4) + { + throw new WrongParametersCountException("Wrong parameter count for current switch"); + } + + string modelName = parameters.GetString(3); + + if (context.ModelsRegistry.FindModel(modelName) is ISwitchModel s) + { + Resistor resistor = new Resistor(name); + Model resistorModel = s; + context.CreateNodes(resistor, parameters.Take(2)); + context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor); + + context.SimulationPreparations.ExecuteActionBeforeSetup( + (simulation) => + { + if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry) + { + resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, s); + + if (!context.Result.FindObject(resistorModel.Name, out _)) + { + stochasticModelsRegistry.RegisterModelInstance(resistorModel); + context.Result.Circuit.Add(resistorModel); + } + } + + double rOff = resistorModel.ParameterSets.GetParameter("roff"); + + string resExpression = $"pos(table(i({parameters.GetString(2)}), @{resistorModel.Name}[ioff], @{resistorModel.Name}[roff] , @{resistorModel.Name}[ion], @{resistorModel.Name}[ron]), {rOff.ToString(CultureInfo.InvariantCulture)})"; + context.SetParameter(resistor, "resistance", resExpression, beforeTemperature: true, onload: true); + }); + return resistor; + } + else + { + CurrentSwitch csw = new CurrentSwitch(name); + context.CreateNodes(csw, parameters); + + // Get the controlling voltage source + if (parameters[2] is WordParameter || parameters[2] is IdentifierParameter) + { + csw.ControllingName = context.ComponentNameGenerator.Generate(parameters.GetString(2)); + } + else + { + throw new WrongParameterTypeException("Voltage source name expected"); + } + + // Get the model + context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => + { + context.ModelsRegistry.SetModel( + csw, + simulation, + parameters.GetString(3), + $"Could not find model {parameters.GetString(3)} for current switch {name}", + (CurrentSwitchModel model) => csw.Model = model.Name, + context.Result); + }); + + // Optional on or off + if (parameters.Count > 4) + { + switch (parameters.GetString(4).ToLower()) + { + case "on": + csw.ParameterSets.SetParameter("on"); + break; + case "off": + csw.ParameterSets.SetParameter("off"); + break; + default: + throw new GeneralReaderException("ON or OFF expected"); + } } - // Get the model - context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => - { - context.ModelsRegistry.SetModel( - csw, - simulation, - parameters.GetString(3), - $"Could not find model {parameters.GetString(3)} for current switch {name}", - (CurrentSwitchModel model) => csw.Model = model.Name, - context.Result); - }); - - // Optional on or off - if (parameters.Count > 4) - { - switch (parameters.GetString(4).ToLower()) - { - case "on": - csw.ParameterSets.SetParameter("on"); - break; - case "off": - csw.ParameterSets.SetParameter("off"); - break; - default: - throw new GeneralReaderException("ON or OFF expected"); - } - } - - return csw; - } - } - } -} + return csw; + } + } + } +} From 1043ef38d3d27a5859eb582282053858d268a0fd Mon Sep 17 00:00:00 2001 From: Marcin Date: Sat, 27 Jul 2019 12:00:43 +0200 Subject: [PATCH 4/6] Refactor simulation configurations + bug fix --- .../Controls/Simulations/DCControlTests.cs | 2 +- .../Controls/Simulations/TranControlTests.cs | 2 +- .../Components/RLCGeneratorTests.cs | 2 +- .../Netlist/Spice/Context/IResultService.cs | 2 +- .../Netlist/Spice/Context/ResultService.cs | 350 +++++++++--------- .../Configurations/MonteCarloConfiguration.cs | 6 +- .../Configurations/SimulationConfiguration.cs | 2 +- .../Netlist/Spice/SpiceNetlistReaderResult.cs | 6 + 8 files changed, 195 insertions(+), 177 deletions(-) rename src/SpiceSharpParser/ModelReaders/Netlist/Spice/{Context => Readers/Controls/Simulations}/Configurations/MonteCarloConfiguration.cs (68%) rename src/SpiceSharpParser/ModelReaders/Netlist/Spice/{Context => Readers/Controls/Simulations}/Configurations/SimulationConfiguration.cs (95%) diff --git a/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/DCControlTests.cs b/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/DCControlTests.cs index d1573f0c..5af70235 100644 --- a/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/DCControlTests.cs +++ b/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/DCControlTests.cs @@ -8,9 +8,9 @@ using System.Linq; using SpiceSharpParser.Common.Evaluation; using SpiceSharpParser.ModelReaders.Netlist.Spice; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Configurations; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Updates; using SpiceSharpParser.ModelReaders.Netlist.Spice.Evaluation; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; using Xunit; namespace SpiceSharpParser.Tests.ModelReaders.Spice.Readers.Controls.Simulations diff --git a/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/TranControlTests.cs b/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/TranControlTests.cs index fea66b92..4192b86c 100644 --- a/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/TranControlTests.cs +++ b/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/Controls/Simulations/TranControlTests.cs @@ -8,9 +8,9 @@ using System.Linq; using SpiceSharpParser.Common.Evaluation; using SpiceSharpParser.ModelReaders.Netlist.Spice; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Configurations; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Updates; using SpiceSharpParser.ModelReaders.Netlist.Spice.Evaluation; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; using Xunit; namespace SpiceSharpParser.Tests.ModelReaders.Spice.Readers.Controls.Simulations diff --git a/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/EntityGenerators/Components/RLCGeneratorTests.cs b/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/EntityGenerators/Components/RLCGeneratorTests.cs index 48e6a098..26cefb80 100644 --- a/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/EntityGenerators/Components/RLCGeneratorTests.cs +++ b/src/SpiceSharpParser.Tests/ModelReaders/Spice/Readers/EntityGenerators/Components/RLCGeneratorTests.cs @@ -33,7 +33,7 @@ public void GenerateSimpleResistor() var resistor = generator.Generate("r1", "R1", "r", parameters, context); Assert.NotNull(resistor); - context.Received().SetParameter(resistor, "resistance", "1.2", false); + context.Received().SetParameter(resistor, "resistance", "1.2", true, onload: false); } [Fact] diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IResultService.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IResultService.cs index 7a7650ba..39d41746 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IResultService.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/IResultService.cs @@ -2,11 +2,11 @@ using SpiceSharp; using SpiceSharp.Circuits; using SpiceSharp.Simulations; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Configurations; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Prints; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; using SpiceSharpParser.Models.Netlist.Spice.Objects; namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ResultService.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ResultService.cs index 86820c1d..86183375 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ResultService.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/ResultService.cs @@ -1,169 +1,181 @@ -using System; -using System.Collections.Generic; -using SpiceSharp; -using SpiceSharp.Circuits; -using SpiceSharp.Simulations; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Configurations; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Prints; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations; -using SpiceSharpParser.Models.Netlist.Spice.Objects; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context -{ - public class ResultService : IResultService - { - /// - /// Initializes a new instance of the class. - /// - /// A SPICE model reader result. - public ResultService(SpiceNetlistReaderResult result) - { - Result = result ?? throw new System.ArgumentNullException(nameof(result)); - } - - /// - /// Gets simulation configuration. - /// - public SimulationConfiguration SimulationConfiguration { get; } = new SimulationConfiguration(); - - /// - /// Gets all simulations. - /// - public IEnumerable Simulations => Result.Simulations; - - /// - /// Gets all exports. - /// - public IEnumerable Exports => Result.Exports; - - /// - /// Gets the circuit. - /// - public Circuit Circuit => Result.Circuit; - - /// - /// Gets the Monte Carlo result. - /// - public MonteCarloResult MonteCarlo => Result.MonteCarloResult; - - /// - /// Gets or sets used random seed. - /// - public int? Seed { get => Result.Seed; set => Result.Seed = value; } - - /// - /// Gets the result where things are added. - /// - private SpiceNetlistReaderResult Result { get; } - - /// - /// Adds warning. - /// - /// Warning to add. - public void AddWarning(string warning) - { - if (warning == null) - { - throw new ArgumentNullException(nameof(warning)); - } - Result.Warnings.Add(warning); - } - - /// - /// Adds comment. - /// - /// Comment to add. - public void AddComment(CommentLine statement) - { - if (statement == null) - { - throw new ArgumentNullException(nameof(statement)); - } - Result.Comments.Add(statement.Text); - } - - /// - /// Adds export to netlist. - /// - /// Export to add. - public void AddExport(Export export) - { - if (export == null) - { - throw new ArgumentNullException(nameof(export)); - } - Result.Exports.Add(export); - } - - /// - /// Adds plot to netlist. - /// - /// Plot to add. - public void AddPlot(XyPlot plot) - { - if (plot == null) - { - throw new ArgumentNullException(nameof(plot)); - } - Result.XyPlots.Add(plot); - } - - /// - /// Adds print to netlist. - /// - /// Print to add. - public void AddPrint(Print print) - { - if (print == null) - { - throw new ArgumentNullException(nameof(print)); - } - Result.Prints.Add(print); - } - - /// - /// Adds entity to netlist. - /// - /// Entity to add. - public void AddEntity(Entity entity) - { - if (entity == null) - { - throw new ArgumentNullException(nameof(entity)); - } - Result.Circuit.Add(entity); - } - - /// - /// Adds simulation to netlist. - /// - /// Simulation to add. - public void AddSimulation(BaseSimulation simulation) - { - if (simulation == null) - { - throw new ArgumentNullException(nameof(simulation)); - } - Result.Simulations.Add(simulation); - } - - /// - /// Finds the object in the result. - /// - /// The object id. - /// The found entity. - /// - /// True if found. - /// - public bool FindObject(string objectId, out Entity entity) - { - if (objectId == null) - { - throw new ArgumentNullException(nameof(objectId)); - } - return Result.Circuit.TryGetEntity(objectId, out entity); - } - } -} +using System; +using System.Collections.Generic; +using SpiceSharp; +using SpiceSharp.Circuits; +using SpiceSharp.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Prints; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; +using SpiceSharpParser.Models.Netlist.Spice.Objects; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context +{ + public class ResultService : IResultService + { + /// + /// Initializes a new instance of the class. + /// + /// A SPICE model reader result. + public ResultService(SpiceNetlistReaderResult result) + { + Result = result ?? throw new System.ArgumentNullException(nameof(result)); + } + + /// + /// Gets simulation configuration. + /// + public SimulationConfiguration SimulationConfiguration => Result.SimulationConfiguration; + + /// + /// Gets all simulations. + /// + public IEnumerable Simulations => Result.Simulations; + + /// + /// Gets all exports. + /// + public IEnumerable Exports => Result.Exports; + + /// + /// Gets the circuit. + /// + public Circuit Circuit => Result.Circuit; + + /// + /// Gets the Monte Carlo result. + /// + public MonteCarloResult MonteCarlo => Result.MonteCarloResult; + + /// + /// Gets or sets used random seed. + /// + public int? Seed + { + get => Result.Seed; + set => Result.Seed = value; + } + + /// + /// Gets the result where things are added. + /// + private SpiceNetlistReaderResult Result { get; } + + /// + /// Adds warning. + /// + /// Warning to add. + public void AddWarning(string warning) + { + if (warning == null) + { + throw new ArgumentNullException(nameof(warning)); + } + + Result.Warnings.Add(warning); + } + + /// + /// Adds comment. + /// + /// Comment to add. + public void AddComment(CommentLine statement) + { + if (statement == null) + { + throw new ArgumentNullException(nameof(statement)); + } + + Result.Comments.Add(statement.Text); + } + + /// + /// Adds export to netlist. + /// + /// Export to add. + public void AddExport(Export export) + { + if (export == null) + { + throw new ArgumentNullException(nameof(export)); + } + + Result.Exports.Add(export); + } + + /// + /// Adds plot to netlist. + /// + /// Plot to add. + public void AddPlot(XyPlot plot) + { + if (plot == null) + { + throw new ArgumentNullException(nameof(plot)); + } + + Result.XyPlots.Add(plot); + } + + /// + /// Adds print to netlist. + /// + /// Print to add. + public void AddPrint(Print print) + { + if (print == null) + { + throw new ArgumentNullException(nameof(print)); + } + + Result.Prints.Add(print); + } + + /// + /// Adds entity to netlist. + /// + /// Entity to add. + public void AddEntity(Entity entity) + { + if (entity == null) + { + throw new ArgumentNullException(nameof(entity)); + } + + Result.Circuit.Add(entity); + } + + /// + /// Adds simulation to netlist. + /// + /// Simulation to add. + public void AddSimulation(BaseSimulation simulation) + { + if (simulation == null) + { + throw new ArgumentNullException(nameof(simulation)); + } + + Result.Simulations.Add(simulation); + } + + /// + /// Finds the object in the result. + /// + /// The object id. + /// The found entity. + /// + /// True if found. + /// + public bool FindObject(string objectId, out Entity entity) + { + if (objectId == null) + { + throw new ArgumentNullException(nameof(objectId)); + } + + return Result.Circuit.TryGetEntity(objectId, out entity); + } + } +} diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Configurations/MonteCarloConfiguration.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Configurations/MonteCarloConfiguration.cs similarity index 68% rename from src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Configurations/MonteCarloConfiguration.cs rename to src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Configurations/MonteCarloConfiguration.cs index 8a640adf..01be9997 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Configurations/MonteCarloConfiguration.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Configurations/MonteCarloConfiguration.cs @@ -1,7 +1,7 @@ -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Configurations -{ - using SpiceSharpParser.Models.Netlist.Spice.Objects; +using SpiceSharpParser.Models.Netlist.Spice.Objects; +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations +{ public class MonteCarloConfiguration { public bool Enabled { get; set; } = false; diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Configurations/SimulationConfiguration.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Configurations/SimulationConfiguration.cs similarity index 95% rename from src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Configurations/SimulationConfiguration.cs rename to src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Configurations/SimulationConfiguration.cs index 10232e1b..2c1867d8 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Context/Configurations/SimulationConfiguration.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/Controls/Simulations/Configurations/SimulationConfiguration.cs @@ -2,7 +2,7 @@ using SpiceSharp.IntegrationMethods; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Sweeps; -namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Configurations +namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations { public class SimulationConfiguration { diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs index adb5ce6f..1c47dcc7 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs @@ -6,6 +6,7 @@ using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Prints; using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; namespace SpiceSharpParser.ModelReaders.Netlist.Spice { @@ -65,6 +66,11 @@ public SpiceNetlistReaderResult(Circuit circuit, string title) /// public MonteCarloResult MonteCarloResult { get; } = new MonteCarloResult(); + /// + /// Gets the simulation configuration. + /// + public SimulationConfiguration SimulationConfiguration { get; } = new SimulationConfiguration(); + /// /// Gets the list of generated prints. /// From fddb5e254da7cb31ceb27d7a8effc7964f80176a Mon Sep 17 00:00:00 2001 From: Marcin Date: Sat, 27 Jul 2019 12:04:05 +0200 Subject: [PATCH 5/6] Remove unused property from SimulationConfiguration --- .../Netlist/Spice/SpiceNetlistReaderResult.cs | 169 +++++++++--------- 1 file changed, 82 insertions(+), 87 deletions(-) diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs index 1c47dcc7..ec830a43 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/SpiceNetlistReaderResult.cs @@ -1,89 +1,84 @@ -using System.Collections.Generic; -using SpiceSharp; -using SpiceSharp.Simulations; -using SpiceSharpParser.Common.Evaluation; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Prints; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations; -using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; - -namespace SpiceSharpParser.ModelReaders.Netlist.Spice -{ - /// - /// A result of reading a SPICE netlist model. - /// - public class SpiceNetlistReaderResult - { - /// - /// Initializes a new instance of the class. - /// - /// The SpiceSharp circuit for the netlist. - /// The title of the netlist. - public SpiceNetlistReaderResult(Circuit circuit, string title) - { - Circuit = circuit ?? throw new System.ArgumentNullException(nameof(circuit)); - Title = title; - } - - /// - /// Gets the title of the netlist. - /// - public string Title { get; } - - /// - /// Gets the circuit from the netlist. - /// - public Circuit Circuit { get; } - - /// - /// Gets the list of simulation from the netlist. - /// - public List Simulations { get; } = new List(); - - /// - /// Gets the list of comments from the netlist. - /// - public List Comments { get; } = new List(); - - /// - /// Gets the warnings created during creating SpiceSharp objects. - /// - public List Warnings { get; } = new List(); - - /// - /// Gets the list of exports from the netlist. - /// - public List Exports { get; } = new List(); - - /// - /// Gets the list of generated X-Y plots. - /// - public List XyPlots { get; } = new List(); - - /// - /// Gets the Monte Carlo Analysis results. - /// - public MonteCarloResult MonteCarloResult { get; } = new MonteCarloResult(); - +using System.Collections.Generic; +using SpiceSharp; +using SpiceSharp.Simulations; +using SpiceSharpParser.Common.Evaluation; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Exporters; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Plots; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Prints; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.Controls.Simulations.Configurations; + +namespace SpiceSharpParser.ModelReaders.Netlist.Spice +{ + /// + /// A result of reading a SPICE netlist model. + /// + public class SpiceNetlistReaderResult + { + /// + /// Initializes a new instance of the class. + /// + /// The SpiceSharp circuit for the netlist. + /// The title of the netlist. + public SpiceNetlistReaderResult(Circuit circuit, string title) + { + Circuit = circuit ?? throw new System.ArgumentNullException(nameof(circuit)); + Title = title; + } + + /// + /// Gets the title of the netlist. + /// + public string Title { get; } + + /// + /// Gets the circuit from the netlist. + /// + public Circuit Circuit { get; } + + /// + /// Gets the list of simulation from the netlist. + /// + public List Simulations { get; } = new List(); + + /// + /// Gets the list of comments from the netlist. + /// + public List Comments { get; } = new List(); + + /// + /// Gets the warnings created during creating SpiceSharp objects. + /// + public List Warnings { get; } = new List(); + + /// + /// Gets the list of exports from the netlist. + /// + public List Exports { get; } = new List(); + + /// + /// Gets the list of generated X-Y plots. + /// + public List XyPlots { get; } = new List(); + + /// + /// Gets the Monte Carlo Analysis results. + /// + public MonteCarloResult MonteCarloResult { get; } = new MonteCarloResult(); + /// /// Gets the simulation configuration. - /// - public SimulationConfiguration SimulationConfiguration { get; } = new SimulationConfiguration(); - - /// - /// Gets the list of generated prints. - /// - public List Prints { get; } = new List(); - - /// - /// Gets or sets the evaluators for simulation. - /// - public IDictionary Evaluators { get; set; } - - /// - /// Gets or sets the used random seed. - /// - public int? Seed { get; set; } - } -} + /// + public SimulationConfiguration SimulationConfiguration { get; } = new SimulationConfiguration(); + + /// + /// Gets the list of generated prints. + /// + public List Prints { get; } = new List(); + + /// + /// Gets or sets the used random seed. + /// + public int? Seed { get; set; } + } +} From 72148bbffb862e107220a2f1c4c3991f9027cbe6 Mon Sep 17 00:00:00 2001 From: Marcin Date: Sun, 28 Jul 2019 10:59:57 +0200 Subject: [PATCH 6/6] Update Spice# package --- .../SpiceSharpParser.CodeAnalysis.csproj | 2 +- .../SpiceSharpParser.IntegrationTests.csproj | 2 +- .../SpiceSharpParser.PerformanceTests.csproj | 2 +- src/SpiceSharpParser.Tests/SpiceSharpParser.Tests.csproj | 4 ++-- src/SpiceSharpParser/SpiceSharpParser.csproj | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/SpiceSharpParser.CodeAnalysis/SpiceSharpParser.CodeAnalysis.csproj b/src/SpiceSharpParser.CodeAnalysis/SpiceSharpParser.CodeAnalysis.csproj index 34a3f306..430aa7cf 100644 --- a/src/SpiceSharpParser.CodeAnalysis/SpiceSharpParser.CodeAnalysis.csproj +++ b/src/SpiceSharpParser.CodeAnalysis/SpiceSharpParser.CodeAnalysis.csproj @@ -20,7 +20,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj b/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj index ba95c5d7..867820d0 100644 --- a/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj +++ b/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj @@ -14,7 +14,7 @@ - + all diff --git a/src/SpiceSharpParser.PerformanceTests/SpiceSharpParser.PerformanceTests.csproj b/src/SpiceSharpParser.PerformanceTests/SpiceSharpParser.PerformanceTests.csproj index a84a09f0..cbf0e910 100644 --- a/src/SpiceSharpParser.PerformanceTests/SpiceSharpParser.PerformanceTests.csproj +++ b/src/SpiceSharpParser.PerformanceTests/SpiceSharpParser.PerformanceTests.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/SpiceSharpParser.Tests/SpiceSharpParser.Tests.csproj b/src/SpiceSharpParser.Tests/SpiceSharpParser.Tests.csproj index 55d34cf1..c180ed1d 100644 --- a/src/SpiceSharpParser.Tests/SpiceSharpParser.Tests.csproj +++ b/src/SpiceSharpParser.Tests/SpiceSharpParser.Tests.csproj @@ -8,8 +8,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/src/SpiceSharpParser/SpiceSharpParser.csproj b/src/SpiceSharpParser/SpiceSharpParser.csproj index 5d9d20fe..7d140c7c 100644 --- a/src/SpiceSharpParser/SpiceSharpParser.csproj +++ b/src/SpiceSharpParser/SpiceSharpParser.csproj @@ -29,7 +29,7 @@ - +