예제 #1
0
        /// <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");
                }
            }
        }
예제 #2
0
파일: Newton.cs 프로젝트: lulzzz/SpiceSharp
        /// <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");
                }
            }
        }