public void AddNet(Net net) { NetVariables[net] = nextFreeVariable; VariableValues.PopFirst().Add(0); VariableIdentifier id = new VariableIdentifier(); id.net = net; VariableData[nextFreeVariable] = id; nextFreeVariable++; }
private void AddNet(Net net) { if (!net.IsFixedVoltage) { NetVariables[net] = nextFreeVariable; VariableValues.Add(0.1); VariableIdentifier id = new VariableIdentifier(); id.type = VariableType.NET; id.net = net; VariableData[nextFreeVariable] = id; nextFreeVariable++; } }
//Add components and nets to be included in the solver private void AddComponent(Component c) { //Due to Kirchoff's Laws, for a component with n pins we only need n-1 equations ComponentVariables[c] = nextFreeVariable; nextFreeVariable += c.GetNumberOfPins() - 1; for (int i = 0; i < c.GetNumberOfPins() - 1; i++) { VariableValues.Add(0.1); VariableIdentifier id = new VariableIdentifier(); id.type = VariableType.COMPONENT; id.component = c; id.pin = i; VariableData[ComponentVariables[c] + i] = id; } }
public virtual double TransientDerivative(TransientSolver solver, int f, VariableIdentifier var) { return(0.0d); }
/* * Evaluate the partial derivatives for the above functions */ public virtual double DCDerivative(DCSolver solver, int f, VariableIdentifier var) { return(0.0d); }
//Run a solve routine, returning whether or not successful //[0] public bool Solve(double tol = 1e-8, int maxIter = 200, bool attemptRamp = true) { int n = VariableValues.Count; double worstTol = 0; //The matrix to solve by Gaussian elimination for the next Newton-Raphson iteration, the rows representing functions. The first n-1 columns are //the Jacobian matrix of partial derivatives (each column representing a variable), and the final column is the value of -f(x) for that function //This is solved to find the values of (x_n+1 - x_n) double[][] matrix = new double[n][]; int i; for (i = 0; i < n; i++) { matrix[i] = new double[n + 1]; } // [1] for (i = 0; i < maxIter; i++) { for (int j = 0; j < n; j++) { VariableIdentifier varData = VariableData[j]; if (varData.type == VariableType.COMPONENT) { //Set the value of -f(x) matrix[j][n] = -varData.component.DCFunction(this, varData.pin); //Populate the matrix of derivatives for (int k = 0; k < n; k++) { matrix[j][k] = varData.component.DCDerivative(this, varData.pin, VariableData[k]); } } else { //Set the value of -f(x) matrix[j][n] = -varData.net.DCFunction(this); //Populate the matrix of derivatives for (int k = 0; k < n; k++) { matrix[j][k] = varData.net.DCDerivative(this, VariableData[k]); } } } worstTol = 0; for (int j = 0; j < n; j++) { if (System.Math.Abs(matrix[j][n]) > worstTol) { worstTol = System.Math.Abs(matrix[j][n]); } } if (worstTol < tol) { break; } //Call the Newton-Raphson solver, which updates VariableValues with their new values Math.newtonIteration(n, VariableValues, matrix); } //If conventional Newton's method solution to find the operating point fails //Fixed nets are ramped up from zero volts to full in 10% steps in an attempt to find the operating point //This works to prevent convergence failures in unstable circuits such as oscillators // [2] if ((i == maxIter) && (worstTol > 1)) { if (attemptRamp) { Console.WriteLine("WARNING: DC simulation failed to converge (error=" + worstTol + ")"); Dictionary <Net, double> netVoltages = new Dictionary <Net, double>(); foreach (Net net in SolverCircuit.Nets) { if ((net.IsFixedVoltage) && (net.NetVoltage != 0)) { netVoltages[net] = net.NetVoltage; net.NetVoltage = 0; } for (int j = 0; j < VariableValues.Count; j++) { VariableValues[j] = 0; } Solve(tol, maxIter, false); TransientSolver rampSolver = new TransientSolver(this); int ticks; ticks = rampSolver.RampUp(netVoltages); for (int j = 0; j < VariableValues.Count; j++) { VariableValues[j] = rampSolver.GetVarValue(j, ticks - 1); } } } else { Console.WriteLine("WARNING: DC Ramp analysis OP failed to converge (error=" + worstTol + ")"); return(false); } } return(true); }