コード例 #1
0
        public void NoRoot()
        {
            Func <double, double> f1 = x => x * x + 4;

            Assert.Throws <NonConvergenceException>(() => Brent.FindRoot(f1, -5, 5, 1e-14, 50));
        }
コード例 #2
0
        private MaxtorqueCapabilityCurve buildMaxtorqueCapabilityCurve(int count = 50, double Imax = 55, double Umax = 140, double max_speed = 6000)
        {
            var mtpa = buildTableMaxtorquePerAmple();

            MaxtorqueCapabilityCurve mtcc = new MaxtorqueCapabilityCurve()
            {
                Imax     = Imax,
                Umax     = Umax,
                MaxSpeed = max_speed,
            };

            // Look for beta to get max torque

            double max_t = mtpa.GetMaxTorqueWithCurrentMagnitude(Imax);
            Fdq    idq   = mtpa.GetCurrentForTorque(max_t);

            // Create PointPairList
            // look for speed1
            var speed1 = Brent.FindRoot(s =>
            {
                var data_ = calculatePointdata(idq.d, idq.q, s);
                var u_    = Math.Sqrt(data_.ud * data_.ud + data_.uq * data_.uq);
                return(u_ - Umax);
            }, 100, max_speed, 1e-3);

            // speed by speed
            int count1 = (int)(speed1 / max_speed * count) + 1;
            int count2 = count - count1;

            for (int i = 1; i < count1 + 1; i++)
            {
                double speed = speed1 * i / count1;

                var data = calculatePointdata(idq.d, idq.q, speed);

                mtcc.speeds.Add(speed);
                mtcc.maxtorques.Add(data.torque);
                mtcc.currents.Add(idq);
                mtcc.voltages.Add(new Fdq()
                {
                    d = data.ud, q = data.uq
                });
                mtcc.power.Add(data.power);
                mtcc.effs.Add(data.efficiency);
            }

            double t = max_t;

            for (int i = 1; i < count2 + 1; i++)
            {
                double speed = speed1 + (max_speed - speed1) * i / count2;

                // find beta which make U=Umax
                //double beta = 0;
                //bool success = Brent.TryFindRoot(b =>
                //{
                //    var data_ = calculatePointdata(Imax * Math.Cos(b * Math.PI / 180), Imax * Math.Sin(b * Math.PI / 180), speed);
                //    var u_ = Math.Sqrt(data_.ud * data_.ud + data_.uq * data_.uq);
                //    return u_ - Umax;
                //}, 100, 180, 1e-5, 100, out beta);

                // Here:
                // Find Id,Iq that bring max torque at speed
                // it is intersect of circle Imax and ellipse Umax/w if Imax < ellipse center (-psiM/Ld)
                // or ellipse center itself if Imax > ellipse center

                Fdq  idq2  = default(Fdq);
                bool found = false;

                var vle = buildVoltageLimitEllipse(speed, 1000, Imax, Umax);

                var maxtorque_point = vle.curve[vle.maxtorque_point];
                var minid_point     = vle.curve[vle.minid_point];

                if (maxtorque_point.Magnitude <= Imax)
                {
                    idq2 = new Fdq {
                        d = maxtorque_point.d, q = maxtorque_point.q
                    };
                    found = true;
                }
                else if (minid_point.Magnitude > Imax) //Imax out of ellipse
                {
                    found = false;
                }
                else
                {
                    var range = Enumerable.Range(0, vle.maxtorque_point);

                    LinearSpline spline = LinearSpline.Interpolate(range.Select(k => vle.curve[k].Magnitude), range.Select(k => vle.curve[k].d));
                    double       id     = spline.Interpolate(Imax);
                    double       iq     = Math.Sqrt(Imax * Imax - id * id);
                    idq2 = new Fdq {
                        d = id, q = iq
                    };
                    found = true;
                }

                if (found)
                {
                    //double id = idq2.d;//Imax * Math.Cos(beta * Math.PI / 180);
                    //double iq = idq2.q;//Imax * Math.Sin(beta * Math.PI / 180);
                    var data = calculatePointdata(idq2.d, idq2.q, speed);

                    mtcc.speeds.Add(speed);
                    mtcc.maxtorques.Add(data.torque);
                    mtcc.currents.Add(idq2);
                    mtcc.voltages.Add(new Fdq()
                    {
                        d = data.ud, q = data.uq
                    });
                    mtcc.power.Add(data.power);
                    mtcc.effs.Add(data.efficiency);
                }
            }

            return(mtcc);
        }
コード例 #3
0
        /// <summary>
        /// Compute the time duration for a <see cref="EbisuModel"/> to decay to
        /// a given percentile.
        /// </summary>
        /// <param name="model">Given model for the fact.</param>
        /// <param name="percentile">Target percentile for the decay.</param>
        /// <param name="coarse">If true, use an approximation for the duration returned.</param>
        /// <param name="tolerance">Allowed tolerance for the duration.</param>
        /// <returns>Duration in time units (of provided model) for the decay to given percentile.</returns>
        private static double ModelToPercentileDecay(
            this EbisuModel model,
            double percentile,
            bool coarse,
            double tolerance)
        {
            if (percentile < 0 || percentile > 1)
            {
                throw new ArgumentException(
                          "Percentiles must be between (0, 1) exclusive",
                          nameof(percentile));
            }

            double alpha = model.Alpha;
            double beta  = model.Beta;
            double t0    = model.Time;

            double logBab           = BetaLn(alpha, beta);
            double logPercentile    = Math.Log(percentile);
            Func <double, double> f = lndelta =>
            {
                return((BetaLn(alpha + Math.Exp(lndelta), beta) - logBab) -
                       logPercentile);
            };

            double bracketWidth = coarse ? 1.0 : 6.0;
            double blow         = -bracketWidth / 2.0;
            double bhigh        = bracketWidth / 2.0;
            double flow         = f(blow);
            double fhigh        = f(bhigh);

            while (flow > 0 && fhigh > 0)
            {
                // Move the bracket up.
                blow   = bhigh;
                flow   = fhigh;
                bhigh += bracketWidth;
                fhigh  = f(bhigh);
            }

            while (flow < 0 && fhigh < 0)
            {
                // Move the bracket down.
                bhigh = blow;
                fhigh = flow;
                blow -= bracketWidth;
                flow  = f(blow);
            }

            if (!(flow > 0 && fhigh < 0))
            {
                throw new EbisuConstraintViolationException($"Failed to bracket: flow={flow}, fhigh={fhigh}");
            }

            if (coarse)
            {
                return((Math.Exp(blow) + Math.Exp(bhigh)) / 2 * t0);
            }

            // Similar to the `root_scalar` api with bracketing
            // See https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.root_scalar.html#scipy.optimize.root_scalar
            var sol = Brent.FindRoot(f, blow, bhigh);

            return(Math.Exp(sol) * t0);
        }