public void When_IsTemperatureDependent_Expect_Reference()
        {
            /*
             * A test for a lowpass RC circuit (DC voltage, resistor, capacitor)
             * The initial voltage on capacitor is 0V. The result should be an exponential converging to dcVoltage.
             * TC1 and TC2 of capacitor is 0.
             * Temperature is 30 degrees.
             */
            double dcVoltage                   = 10;
            var    resistorResistance          = 10e3; // 10000;
            double factor                      = (1.0 + 3.0 * 1.1 + 3.0 * 3.0 * 2.1);
            var    capacitance                 = 1e-6;
            var    capacitanceAfterTemperature = capacitance * factor;

            var tau = resistorResistance * capacitanceAfterTemperature;

            var capacitor = new Capacitor("C1", "OUT", "0", capacitance);
            var model     = new CapacitorModel("model C1");

            model.Parameters.TemperatureCoefficient1 = 1.1;
            model.Parameters.TemperatureCoefficient2 = 2.1;
            capacitor.Model = model.Name;

            // Build circuit
            var ckt = new Circuit(
                model,
                capacitor,
                new Resistor("R1", "IN", "OUT", resistorResistance),
                new VoltageSource("V1", "IN", "0", dcVoltage));

            // Create simulation, exports and references
            var tran = new Transient("tran", 1e-8, 10e-6);

            tran.TimeParameters.InitialConditions["OUT"] = 0.0;

            tran.BeforeTemperature += (sender, args) =>
            {
                var state = tran.GetState <ITemperatureSimulationState>();
                ((TemperatureSimulationState)state).Temperature = Constants.CelsiusKelvin + 30.0;
            };

            IExport <double>[]      exports    = { new RealPropertyExport(tran, "C1", "v") };
            Func <double, double>[] references = { t => dcVoltage * (1.0 - Math.Exp(-t / tau)) };

            // Run
            AnalyzeTransient(tran, ckt, exports, references);
            DestroyExports(exports);
        }
        public override Context.Models.Model Generate(string id, string type, ParameterCollection parameters, ICircuitContext context)
        {
            switch (type.ToLower())
            {
            case "res":
            case "r":
                var model = new ResistorModel(id);
                SetParameters(context, model, parameters);
                return(new Context.Models.Model(id, model, model.Parameters));

            case "c":
                var model2 = new CapacitorModel(id);
                SetParameters(context, model2, parameters);
                return(new Context.Models.Model(id, model2, model2.Parameters));
            }

            return(null);
        }
        public void When_CapacitorIsTemperatureInvariant_Expect_Reference()
        {
            /*
             * A test for a lowpass RC circuit (DC voltage, resistor, capacitor)
             * The initial voltage on capacitor is 0V. The result should be an exponential converging to dcVoltage.
             * TC1 and TC2 of capacitor is 0.
             * Temperature is 30 degrees.
             */
            double dcVoltage          = 10;
            var    resistorResistance = 10e3; // 10000;
            var    capacitance        = 1e-6; // 0.000001;
            var    tau = resistorResistance * capacitance;

            var capacitor = new Capacitor("C1", "OUT", "0", capacitance);
            var model     = new CapacitorModel("model C1");

            model.ParameterSets.Get <ModelBaseParameters>().TemperatureCoefficient1.Value = 0.0;
            model.ParameterSets.Get <ModelBaseParameters>().TemperatureCoefficient2.Value = 0.0;
            capacitor.Model = model.Name;

            // Build circuit
            var ckt = new Circuit(
                model,
                capacitor,
                new Resistor("R1", "IN", "OUT", resistorResistance),
                new VoltageSource("V1", "IN", "0", dcVoltage));

            // Create simulation, exports and references
            var tran = new Transient("tran", 1e-8, 10e-6);

            tran.Configurations.Get <TimeConfiguration>().InitialConditions["OUT"] = 0.0;

            tran.BeforeTemperature += (sender, args) =>
            {
                ((BaseSimulationState)args.State).Temperature = Constants.CelsiusKelvin + 30.0;
            };

            Export <double>[]       exports    = { new RealPropertyExport(tran, "C1", "v") };
            Func <double, double>[] references = { t => dcVoltage * (1.0 - Math.Exp(-t / tau)) };

            // Run
            AnalyzeTransient(tran, ckt, exports, references);
            DestroyExports(exports);
        }
        public override SpiceSharp.Components.Model Generate(string id, string type, ParameterCollection parameters, ICircuitContext context)
        {
            SpiceSharp.Components.Model model = null;

            switch (type.ToLower())
            {
            case "res":
            case "r":
                model = new ResistorModel(id);
                break;

            case "c":
                model = new CapacitorModel(id);
                break;
            }

            if (model != null)
            {
                SetParameters(context, model, parameters);
            }

            return(model);
        }
        /// <summary>
        ///  Generates a new capacitor.
        /// </summary>
        /// <param name="name">Name of capacitor to generate.</param>
        /// <param name="parameters">Parameters and pins for capacitor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of capacitor.
        /// </returns>
        protected SpiceSharp.Components.IComponent GenerateCap(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count == 3)
            {
                // CXXXXXXX N1 N2 VALUE
                var evalContext = context.Evaluator.GetEvaluationContext();

                var    something  = parameters[2];
                string expression = null;

                if (something is AssignmentParameter asp)
                {
                    expression = $"({asp.Value}) * x";
                }
                else
                {
                    expression = $"({something.Image}) * x";
                }

                if (evalContext.HaveSpiceProperties(expression) || evalContext.HaveFunctions(expression))
                {
                    BehavioralCapacitor behavioralCapacitor = new BehavioralCapacitor(name);
                    context.CreateNodes(behavioralCapacitor, parameters.Take(BehavioralCapacitor.BehavioralCapacitorPinCount));

                    behavioralCapacitor.Parameters.Expression  = expression;
                    behavioralCapacitor.Parameters.ParseAction = (expression) =>
                    {
                        var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                        return(parser.Resolve(expression));
                    };

                    evalContext.Parameters.Add("x", new SpiceSharpParser.Common.Evaluation.Expressions.ConstantExpression(1));

                    if (evalContext.HaveFunctions(expression))
                    {
                        context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                        {
                            behavioralCapacitor.Parameters.Expression = expression.ToString();

                            behavioralCapacitor.Parameters.ParseAction = (expression) =>
                            {
                                var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity);
                                return(parser.Resolve(expression));
                            };
                        });
                    }

                    evalContext.Parameters.Remove("x");

                    return(behavioralCapacitor);
                }
            }

            var capacitor = new Capacitor(name);

            context.CreateNodes(capacitor, parameters);

            // Get TC Parameter
            Parameter tcParameter = parameters.FirstOrDefault(
                p => p is AssignmentParameter ap && ap.Name.Equals(
                    "tc",
                    false ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));

            if (tcParameter != null)
            {
                parameters.Remove(tcParameter);
            }

            bool modelBased = false;

            if (parameters.Count == 3)
            {
                // CXXXXXXX N1 N2 VALUE
                if (parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2), true, false);
                }
                else
                {
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"Wrong parameter value for capacitance",
                            parameters.LineInfo));
                    return(null);
                }
            }
            else
            {
                // CXXXXXXX N1 N2 <VALUE> <MNAME> <L=LENGTH> <W=WIDTH> <IC=VAL>

                // Examples:
                // CMOD 3 7 CMODEL L = 10u W = 1u
                // CMOD 3 7 CMODEL L = 10u W = 1u IC=1
                // CMOD 3 7 1.3 IC=1
                if (parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2), true, false);
                }
                else
                {
                    context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                    {
                        context.ModelsRegistry.SetModel(
                            capacitor,
                            simulation,
                            parameters.Get(2),
                            $"Could not find model {parameters.Get(2)} for capacitor {name}",
                            (Context.Models.Model model) => capacitor.Model = model.Name,
                            context.Result);
                    });

                    modelBased = true;
                }

                SetParameters(context, capacitor, parameters.Skip(3), true);

                if (modelBased)
                {
                    var bp = capacitor.GetParameterSet <ModelParameters>();

                    /*if (bp == null || !bp.Length.Given)
                     * {
                     *  context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                     *      ValidationEntryLevel.Warning,
                     *      $"L needs to be specified", parameters.LineInfo));
                     *  return null;
                     * }*/
                }
            }

            if (tcParameter != null)
            {
                var tcParameterAssignment = tcParameter as AssignmentParameter;

                if (tcParameterAssignment == null)
                {
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"TC needs to be assignment parameter",
                            parameters.LineInfo));
                    return(null);
                }

                if (modelBased)
                {
                    var model = context.ModelsRegistry.FindModelEntity(parameters.Get(2).Image);

                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0], true, false);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1], true, false);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
                else
                {
                    var model = new CapacitorModel(capacitor.Name + "_default_model");
                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0], true, false);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1], true, false);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.ModelsRegistry.RegisterModelInstance(new Context.Models.Model(model.Name, model, model.Parameters));
                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
            }

            return(capacitor);
        }
        /// <summary>
        ///  Generates a new capacitor.
        /// </summary>
        /// <param name="name">Name of capacitor to generate.</param>
        /// <param name="parameters">Parameters and pins for capacitor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of capacitor.
        /// </returns>
        protected SpiceSharp.Components.Component GenerateCap(string name, ParameterCollection parameters, ICircuitContext context)
        {
            var capacitor = new Capacitor(name);

            context.CreateNodes(capacitor, parameters);

            // Get TC Parameter
            Parameter tcParameter = parameters.FirstOrDefault(
                p => p is AssignmentParameter ap && ap.Name.Equals(
                    "tc",
                    context.CaseSensitivity.IsEntityParameterNameCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));

            if (tcParameter != null)
            {
                parameters.Remove(tcParameter);
            }

            bool modelBased = false;

            if (parameters.Count == 3)
            {
                // CXXXXXXX N1 N2 VALUE
                if (parameters[2] is ExpressionParameter || parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2));
                }
                else
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"Wrong parameter value for capacitance", parameters.LineInfo));
                    return(null);
                }
            }
            else
            {
                // CXXXXXXX N1 N2 <VALUE> <MNAME> <L=LENGTH> <W=WIDTH> <IC=VAL>

                // Examples:
                // CMOD 3 7 CMODEL L = 10u W = 1u
                // CMOD 3 7 CMODEL L = 10u W = 1u IC=1
                // CMOD 3 7 1.3 IC=1
                if (parameters[2] is ExpressionParameter || parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2));
                }
                else
                {
                    context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                    {
                        context.ModelsRegistry.SetModel(
                            capacitor,
                            simulation,
                            parameters.Get(2),
                            $"Could not find model {parameters.Get(2)} for capacitor {name}",
                            (CapacitorModel model) => capacitor.Model = model.Name,
                            context.Result);
                    });

                    modelBased = true;
                }

                SetParameters(context, capacitor, parameters.Skip(3), true);

                if (modelBased)
                {
                    var bp = capacitor.ParameterSets[typeof(SpiceSharp.Components.CapacitorBehaviors.BaseParameters)] as SpiceSharp.Components.CapacitorBehaviors.BaseParameters;
                    if (bp == null || !bp.Length.Given)
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                          ValidationEntryLevel.Warning,
                                                                          $"L needs to be specified", parameters.LineInfo));
                        return(null);
                    }
                }
            }

            if (tcParameter != null)
            {
                var tcParameterAssignment = tcParameter as AssignmentParameter;

                if (tcParameterAssignment == null)
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"TC needs to be assignment parameter", parameters.LineInfo));
                    return(null);
                }

                if (modelBased)
                {
                    var model = context.ModelsRegistry.FindModel <CapacitorModel>(parameters.Get(2).Image);

                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0]);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1]);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
                else
                {
                    var model = new CapacitorModel(capacitor.Name + "_default_model");
                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0]);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1]);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.ModelsRegistry.RegisterModelInstance(model);
                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
            }

            return(capacitor);
        }