/// <summary> /// Execute using the secant method /// </summary> /// <param name="ckt">Circuit</param> public override void Execute(Circuit ckt) { // Initialize double xmin = Math.Min(Minimum, Maximum); double xmax = Math.Max(Minimum, Maximum); // Find out xmin and xmax Apply(this, ckt, xmin); double ymin = Measurement.Measure(ckt) - Target; Apply(this, ckt, xmax); double ymax = Measurement.Measure(ckt) - Target; double width = xmax - xmin; double tol = Math.Abs(xmax) * RelTol + AbsTol; // Make sure the signs are opposite if (ymin == 0.0) { Result = xmin; return; } if (ymax == 0.0) { Result = xmax; return; } if (ymin * ymax > 0.0) { throw new DesignException("Cannot find zero"); } // Perform a bisection step until the width has reached half the tolerance while (width > tol) { // Get the intersection with y=0 double m = (ymax - ymin) / (xmax - xmin); double x = xmin - ymin / m; Apply(this, ckt, x); double y = Measurement.Measure(ckt) - Target; tol = Math.Abs(x) * RelTol + AbsTol; // Narrow down our search region depending on the sign if (ymin * y >= 0.0) { xmin = x; } else { xmax = x; } width = xmax - xmin; Result = x; // Check iteration count Iterations++; if (Iterations > MaxIterations) { throw new DesignException("Maximum iteration count reached"); } } }
/// <summary> /// Execute method of Newton /// </summary> /// <param name="ckt">Circuit</param> public override void Execute(Circuit ckt) { // Initialize double xmin = Math.Min(Minimum, Maximum); double xmax = Math.Max(Minimum, Maximum); Result = Start; if (Result < xmin) { Result = xmin; } if (Result > xmax) { Result = xmax; } double error = double.PositiveInfinity; double tol = 0.0; Apply(this, ckt, Result); double y = Measurement.Measure(ckt); // Start iterations while (Math.Abs(error) > tol) { // Numerical derivative calculation double delta = RelDiff * Result + AbsDiff; double m = 0.0; if (Result - delta < xmin) { Apply(this, ckt, Result + delta); m = (Measurement.Measure(ckt) - y) / delta; } else { Apply(this, ckt, Result - delta); m = (y - Measurement.Measure(ckt)) / delta; } if (m == 0.0) { m = Math.Sign(error) * 1e-12; } // Calculate the new point double nx = Result - (y - Target) / m; if (nx < xmin) { nx = xmin; } if (nx > xmax) { nx = xmax; } Apply(this, ckt, nx); y = Measurement.Measure(ckt); error = (nx - Result) / Math.Abs(Math.Max(nx, Result)); Result = nx; tol = Math.Max(Math.Abs(nx), Math.Abs(Target)) * RelTol + AbsTol; // Track iteration count Iterations++; if (Iterations > MaxIterations) { throw new DesignException("Maximum iteration count reached"); } } }