/// <summary> /// A default method for registering variables with a real function builder. /// </summary> /// <param name="sender">The sender.</param> /// <param name="args">The arguments.</param> public static void RegisterDefaultBuilder(object sender, BuilderCreatedEventArgs <double> args) { var bp = args.Context.GetParameterSet <Parameters>(); var context = args.Context; var builder = args.Builder; var variables = new Dictionary <string, IVariable <double> >(bp.VariableComparer); // Register the default functions builder.RegisterDefaultFunctions(); // Temperature if (context.TryGetState <ITemperatureSimulationState>(out var tempState)) { variables.Add("temperature", new FuncVariable <double>("temperature", () => tempState.Temperature, _kelvin)); } // Time variable if (context.TryGetState <IIntegrationMethod>(out var method)) { var time = context.GetState <ITimeSimulationState>(); // Time variable variables.Add("time", new FuncVariable <double>("time", () => method.Time, _seconds)); // Allow using a ddt/ddt_slope function var comparer = RealFunctionBuilderHelper.Defaults.Comparer; builder.FunctionFound += (sender, args) => { if (!args.Created) { // Take care of the actual value if (comparer.Equals("ddt", args.Function.Name)) { var derivative = method.CreateDerivative(); args.ILState.Call(value => { derivative.Value = value; derivative.Derive(); return(derivative.Derivative); }, args.Function.Arguments); args.Created = true; } else if (comparer.Equals("idt", args.Function.Name)) { var integral = method.CreateIntegral(); args.ILState.Call(value => { // Don't integrate if we're doing DC analysis if (time.UseDc) { return(integral.Value); } integral.Derivative = value; integral.Integrate(); return(integral.Value); }, args.Function.Arguments); args.Created = true; } // Take care of the derivative else if (comparer.Equals("ddt_slope", args.Function.Name)) { args.ILState.Call(value => value * method.Slope, args.Function.Arguments); args.Created = true; } else if (comparer.Equals("idt_slope", args.Function.Name)) { var config = context.GetSimulationParameterSet <BiasingParameters>(); args.ILState.Call(value => { if (time.UseDc) { return(1e12); // This is basically putting a large resistance in parallel... } return(value / method.Slope); }, args.Function.Arguments); args.Created = true; } } }; } else { // Time variable variables.Add("time", new ConstantVariable <double>("time", 0.0, _seconds)); // Allow using a ddt/ddt_slope function var comparer = RealFunctionBuilderHelper.Defaults.Comparer; builder.FunctionFound += (sender, args) => { if (!args.Created) { if (comparer.Equals("ddt", args.Function.Name) || comparer.Equals("ddt_slope", args.Function.Name)) { args.ILState.Push(0.0); args.Created = true; } else if (comparer.Equals("idt", args.Function.Name)) { args.ILState.Push(0.0); args.Created = true; } else if (comparer.Equals("idt_slope", args.Function.Name)) { args.ILState.Push(1e-12); args.Created = true; } } }; } // Iteration control if (context.TryGetState <IIterationSimulationState>(out var iterState)) { variables.Add("gmin", new FuncVariable <double>("gmin", () => iterState.Gmin, _mho)); variables.Add("sourcefactor", new FuncVariable <double>("sourcefactor", () => iterState.SourceFactor, _scalar)); } // Some standard constants variables.Add("pi", new ConstantVariable <double>("pi", Math.PI, _scalar)); variables.Add("e", new ConstantVariable <double>("e", Math.Exp(1.0), _scalar)); variables.Add("boltz", new ConstantVariable <double>("boltz", Constants.Boltzmann, _joulesPerKelvin)); variables.Add("planck", new ConstantVariable <double>("planck", 6.626207004e-34, _joulesSeconds)); variables.Add("echarge", new ConstantVariable <double>("echarge", Constants.Charge, Units.Coulomb)); variables.Add("kelvin", new ConstantVariable <double>("kelvin", -Constants.CelsiusKelvin, _kelvin)); // Register these variables builder.VariableFound += (sender, args) => { if (args.Variable == null && variables.TryGetValue(args.Node.Name, out var variable)) { args.Variable = variable; } }; }
/// <summary> /// A default method for registering variables with a real function builder. /// </summary> /// <param name="sender">The sender.</param> /// <param name="args">The arguments.</param> public static void RegisterDefaultBuilder(object sender, BuilderCreatedEventArgs <Complex> args) { var bp = args.Context.GetParameterSet <Parameters>(); var context = args.Context; var builder = args.Builder; var variables = new Dictionary <string, IVariable <Complex> >(bp.VariableComparer); // Register the default functions builder.RegisterDefaultFunctions(); // Temperature if (context.TryGetState <ITemperatureSimulationState>(out var tempState)) { variables.Add("temperature", new FuncVariable <Complex>("temperature", () => tempState.Temperature, _kelvin)); } // Time variable if (context.TryGetState <IIntegrationMethod>(out var method)) { variables.Add("time", new FuncVariable <Complex>("time", () => method.Time, _seconds)); } // Iteration control if (context.TryGetState <IIterationSimulationState>(out var iterState)) { variables.Add("gmin", new FuncVariable <Complex>("gmin", () => iterState.Gmin, _mho)); variables.Add("sourcefactor", new FuncVariable <Complex>("sourcefactor", () => iterState.SourceFactor, _scalar)); } // AC analysis if (context.TryGetState <IComplexSimulationState>(out var cplxState)) { var comparer = RealFunctionBuilderHelper.Defaults.Comparer; builder.FunctionFound += (sender, args) => { if (!args.Created) { if (comparer.Equals("ddt_slope", args.Function.Name)) { args.ILState.Call(value => value * cplxState.Laplace, args.Function.Arguments); args.Created = true; } else if (comparer.Equals("idt_slope", args.Function.Name)) { args.ILState.Call(value => cplxState.Laplace.Imaginary.Equals(0.0) ? double.PositiveInfinity : value / cplxState.Laplace, args.Function.Arguments); args.Created = true; } } }; } // Some standard constants variables.Add("pi", new ConstantVariable <Complex>("pi", Math.PI, _scalar)); variables.Add("e", new ConstantVariable <Complex>("e", Math.Exp(1.0), _scalar)); variables.Add("boltz", new ConstantVariable <Complex>("boltz", Constants.Boltzmann, _joulesPerKelvin)); variables.Add("planck", new ConstantVariable <Complex>("planck", 6.626207004e-34, _joulesSeconds)); variables.Add("echarge", new ConstantVariable <Complex>("echarge", Constants.Charge, Units.Coulomb)); variables.Add("kelvin", new ConstantVariable <Complex>("kelvin", -Constants.CelsiusKelvin, _kelvin)); // Register these variables builder.VariableFound += (sender, args) => { if (args.Variable == null && variables.TryGetValue(args.Node.Name, out var variable)) { args.Variable = variable; } }; }