/// <summary> /// Generates a current switch. /// </summary> /// <param name="name">Name of current switch.</param> /// <param name="parameters">Parameters of current switch.</param> /// <param name="context">Reading context.</param> /// <returns> /// A new instance of current switch. /// </returns> private IEntity GenerateCurrentSwitch(string name, ParameterCollection parameters, ICircuitContext context) { if (parameters.Count < 4) { context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for current switch", parameters.LineInfo)); return(null); } string modelName = parameters.Get(3).Image; var model = context.ModelsRegistry.FindModel(modelName); if (model.Entity is ISwitchModel) { BehavioralResistor resistor = new BehavioralResistor(name); Model resistorModel = model; context.CreateNodes(resistor, parameters.Take(2)); var ic = $"i({parameters.Get(2)})"; var iswitchModelParameters = resistorModel.Parameters as ISwitchModelParameters; double iOff = iswitchModelParameters.OffCurrent; double rOff = iswitchModelParameters.OffResistance; double iOn = iswitchModelParameters.OnCurrent; double rOn = iswitchModelParameters.OnResistance; double lm = Math.Log(Math.Sqrt(rOn * rOff)); double lr = Math.Log(rOn / rOff); double im = (iOn + iOff) / 2.0; double id = iOn - iOff; var resExpression = GetISwitchExpression(iOff, rOff, iOn, rOn, ic, lm, lr, im, id); resistor.Parameters.Expression = resExpression; resistor.Parameters.ParseAction = (expression) => { var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity); return(parser.Resolve(expression)); }; context.SimulationPreparations.ExecuteActionAfterSetup( (simulation) => { if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry) { resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, model); if (!context.Result.FindObject(resistorModel.Name, out _)) { stochasticModelsRegistry.RegisterModelInstance(resistorModel); } } iOff = iswitchModelParameters.OffCurrent; rOff = iswitchModelParameters.OffResistance; iOn = iswitchModelParameters.OnCurrent; rOn = iswitchModelParameters.OnResistance; lm = Math.Log(Math.Sqrt(rOn * rOff)); lr = Math.Log(rOn / rOff); im = (iOn + iOff) / 2.0; id = iOn - iOff; resExpression = GetISwitchExpression(iOff, rOff, iOn, rOn, ic, lm, lr, im, id); resistor.Parameters.Expression = resExpression; resistor.Parameters.ParseAction = (expression) => { var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity); return(parser.Resolve(expression)); }; }); return(resistor); } CurrentSwitch csw = new CurrentSwitch(name); context.CreateNodes(csw, parameters); // Get the controlling voltage source if (parameters[2] is WordParameter || parameters[2] is IdentifierParameter) { csw.ControllingSource = context.NameGenerator.GenerateObjectName(parameters.Get(2).Image); } else { context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Voltage source name expected", parameters.LineInfo)); return(null); } // Get the model context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => { context.ModelsRegistry.SetModel( csw, simulation, parameters.Get(3), $"Could not find model {parameters.Get(3)} for current switch {name}", (Context.Models.Model switchModel) => csw.Model = switchModel.Name, context.Result); }); // Optional on or off if (parameters.Count > 4) { switch (parameters.Get(4).Image.ToLower()) { case "on": csw.SetParameter("on", true); break; case "off": csw.SetParameter("off", true); break; default: context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "ON or OFF expected", parameters.LineInfo)); return(csw); } } return(csw); }
/// <summary> /// Generates a voltage switch. /// </summary> /// <param name="name">Name of voltage switch to generate.</param> /// <param name="parameters">Parameters for voltage switch.</param> /// <param name="context">Reading context.</param> /// <returns> /// A new voltage switch. /// </returns> protected IEntity GenerateVoltageSwitch(string name, ParameterCollection parameters, ICircuitContext context) { if (parameters.Count < 5) { context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for voltage switch", parameters.LineInfo)); return(null); } string modelName = parameters.Get(4).Image; var model = context.ModelsRegistry.FindModel(modelName); if (model.Entity is VSwitchModel) { BehavioralResistor resistor = new BehavioralResistor(name); Model resistorModel = model; context.CreateNodes(resistor, parameters.Take(BehavioralResistor.BehavioralResistorPinCount)); var vSwitchModelParameters = resistorModel.Parameters as VSwitchModelParameters; double vOff = vSwitchModelParameters.OffVoltage; double rOff = vSwitchModelParameters.OffResistance; double vOn = vSwitchModelParameters.OnVoltage; double rOn = vSwitchModelParameters.OnResistance; string vc = $"v({parameters.Get(2)}, {parameters.Get(3)})"; double lm = Math.Log(Math.Sqrt(rOn * rOff)); double lr = Math.Log(rOn / rOff); double vm = (vOn + vOff) / 2.0; double vd = vOn - vOff; string resExpression = GetVSwitchExpression(vOff, rOff, vOn, rOn, vc, lm, lr, vm, vd); resistor.Parameters.Expression = resExpression; resistor.Parameters.ParseAction = (expression) => { var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity); return(parser.Resolve(expression)); }; context.SimulationPreparations.ExecuteActionAfterSetup( (simulation) => { if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry) { resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, model); if (!context.Result.FindObject(resistorModel.Name, out _)) { stochasticModelsRegistry.RegisterModelInstance(resistorModel); } } vOff = vSwitchModelParameters.OffVoltage; rOff = vSwitchModelParameters.OffResistance; vOn = vSwitchModelParameters.OnVoltage; rOn = vSwitchModelParameters.OnResistance; lm = Math.Log(Math.Sqrt(rOn * rOff)); lr = Math.Log(rOn / rOff); vm = (vOn + vOff) / 2.0; vd = vOn - vOff; resExpression = GetVSwitchExpression(vOff, rOff, vOn, rOn, vc, lm, lr, vm, vd); resistor.Parameters.Expression = resExpression; resistor.Parameters.ParseAction = (expression) => { var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity); return(parser.Resolve(expression)); }; }); return(resistor); } VoltageSwitch vsw = new VoltageSwitch(name); context.CreateNodes(vsw, parameters); context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => { context.ModelsRegistry.SetModel( vsw, simulation, parameters.Get(4), $"Could not find model {parameters.Get(4)} for voltage switch {name}", (Context.Models.Model model2) => { vsw.Model = model2.Name; }, context.Result); }); // Optional ON or OFF if (parameters.Count == 6) { switch (parameters.Get(5).Image.ToLower()) { case "on": vsw.SetParameter("on", true); break; case "off": vsw.SetParameter("off", true); break; default: context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "ON or OFF expected", parameters.LineInfo)); return(vsw); } } else if (parameters.Count > 6) { context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Too many parameters for voltage switch", parameters.LineInfo)); return(vsw); } return(vsw); }
/// <summary> /// Generate resistor. /// </summary> /// <param name="name">Name of resistor to generate.</param> /// <param name="parameters">Parameters and pins for resistor.</param> /// <param name="context">Reading context.</param> /// <returns> /// A new instance of resistor. /// </returns> protected IEntity GenerateRes(string name, ParameterCollection parameters, ICircuitContext context) { if (parameters.Count == 3) { var evalContext = context.Evaluator.GetEvaluationContext(); // RName Node1 Node2 something var something = parameters[2]; string expression = null; if (something is AssignmentParameter asp) { expression = asp.Value; } else { expression = something.Image; } if (evalContext.HaveSpiceProperties(expression) || evalContext.HaveFunctions(expression)) { BehavioralResistor behavioralResistor = new BehavioralResistor(name); context.CreateNodes(behavioralResistor, parameters.Take(BehavioralResistor.BehavioralResistorPinCount)); behavioralResistor.Parameters.Expression = expression; behavioralResistor.Parameters.ParseAction = (expression) => { var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity); return(parser.Resolve(expression)); }; if (evalContext.HaveFunctions(expression)) { context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => { behavioralResistor.Parameters.Expression = expression.ToString(); behavioralResistor.Parameters.ParseAction = (expression) => { var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity); return(parser.Resolve(expression)); }; }); } return(behavioralResistor); } } Resistor res = new Resistor(name); context.CreateNodes(res, parameters); if (parameters.Count == 3) { // RName Node1 Node2 something var something = parameters[2]; // Check if something is a model name if ((something is WordParameter || something is IdentifierParameter) && context.ModelsRegistry.FindModel(parameters.Get(2).Image) != null) { // RName Node1 Node2 modelName context.Result.Validation.Add( new ValidationEntry( ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"R parameter needs to be specified", parameters.LineInfo)); return(null); } // Check if something can be resistance if (!(something is WordParameter || something is IdentifierParameter || something is ValueParameter || something is ExpressionParameter || (something is AssignmentParameter ap && (ap.Name.ToLower() == "r" || ap.Name.ToLower() == "resistance")))) { context.Result.Validation.Add( new ValidationEntry( ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Third parameter needs to represent resistance of resistor", parameters.LineInfo)); return(null); } // Set resistance if (something is AssignmentParameter asp) { context.SetParameter(res, "resistance", asp, true, false); } else { context.SetParameter(res, "resistance", something, true, false); } } else { var resistorParameters = new List <Parameter>(parameters.Skip(Resistor.ResistorPinCount).ToArray()); // RName Node1 Node2 something param1 ... if (resistorParameters.Count == 0) { context.Result.Validation.Add( new ValidationEntry( ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Resistor doesn't have at least 3 parameters", parameters.LineInfo)); return(null); } var something = resistorParameters[0]; // Check if something is a model name bool hasModelSyntax = (something is WordParameter || something is IdentifierParameter) && context.ModelsRegistry.FindModel(something.Image) != null; bool hasTcParameter = parameters.Any( p => p is AssignmentParameter ap && ap.Name.Equals( "tc", false ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase)); AssignmentParameter tcParameter = null; if (hasTcParameter) { tcParameter = (AssignmentParameter)parameters.Single( p => p is AssignmentParameter ap && ap.Name.Equals( "tc", false ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase)); resistorParameters.Remove(tcParameter); } if (hasModelSyntax) { var modelNameParameter = resistorParameters[0]; // Ignore tc parameter on resistor ... context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) => { context.ModelsRegistry.SetModel( res, simulation, modelNameParameter, $"Could not find model {modelNameParameter} for resistor {name}", (Context.Models.Model model) => res.Model = model.Name, context.Result); }); resistorParameters.RemoveAt(0); if (resistorParameters.Count > 0 && (resistorParameters[0] is WordParameter || resistorParameters[0] is IdentifierParameter || resistorParameters[0] is ValueParameter || resistorParameters[0] is ExpressionParameter)) { context.SetParameter(res, "resistance", resistorParameters[0].Image, true, false); resistorParameters.RemoveAt(0); } } else { if (hasTcParameter) { var model = new ResistorModel(res.Name + "_default_model"); if (tcParameter.Values.Count == 2) { context.SetParameter(model, "tc1", tcParameter.Values[0]); context.SetParameter(model, "tc2", tcParameter.Values[1]); } else { context.SetParameter(model, "tc1", tcParameter.Value); } context.ModelsRegistry.RegisterModelInstance(new Context.Models.Model(model.Name, model, model.Parameters)); res.Model = model.Name; context.Result.AddEntity(model); } // Check if something can be resistance var resistanceParameter = resistorParameters[0]; if (!(resistanceParameter is WordParameter || resistanceParameter is IdentifierParameter || resistanceParameter is ValueParameter || resistanceParameter is ExpressionParameter || (resistanceParameter is AssignmentParameter ap && (ap.Name.ToLower() == "r" || ap.Name.ToLower() == "resistance")))) { context.Result.Validation.Add( new ValidationEntry( ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Invalid value for resistance", parameters.LineInfo)); return(null); } if (resistanceParameter is AssignmentParameter asp) { context.SetParameter(res, "resistance", asp.Value, true, false); } else { context.SetParameter(res, "resistance", resistanceParameter.Image, true, false); } resistorParameters.RemoveAt(0); } foreach (var parameter in resistorParameters) { if (parameter is AssignmentParameter ap) { try { context.SetParameter(res, ap.Name, ap.Value); } catch (Exception e) { context.Result.Validation.Add( new ValidationEntry( ValidationEntrySource.Reader, ValidationEntryLevel.Error, $"Can't set parameter for resistor: '{parameter.Image}'", parameters.LineInfo, exception: e)); return(null); } } else { context.Result.Validation.Add( new ValidationEntry( ValidationEntrySource.Reader, ValidationEntryLevel.Error, $"Invalid parameter for resistor: '{parameter.Image}'", parameters.LineInfo)); return(null); } } } return(res); }