public override void update()
        {
            sectionHelpers_.Clear();
            if (size_ == 2)   //single period
            {
                ISectionHelper singleHelper = new EverywhereConstantHelper(yBegin_[1], 0.0, xBegin_[0]);
                sectionHelpers_.Add(xBegin_[1], singleHelper);
                extrapolationHelper_ = singleHelper;
                return;
            }

            List <double> f = new InitializedList <double>(size_);

            sectionHelpers_ = new Dictionary <double, ISectionHelper>(preSectionHelpers_);
            int startPoint = sectionHelpers_.Count + 1;

            //first derive the boundary forwards.
            for (int i = startPoint; i < size_ - 1; ++i)
            {
                double dxPrev = xBegin_[i] - xBegin_[i - 1];
                double dx     = xBegin_[i + 1] - xBegin_[i];
                f[i] = dxPrev / (dx + dxPrev) * yBegin_[i]
                       + dx / (dx + dxPrev) * yBegin_[i + 1];
            }

            if (startPoint > 1)
            {
                f[startPoint - 1] = preSectionHelpers_.Last().Value.fNext();
            }
            if (startPoint == 1)
            {
                f[0] = 1.5 * yBegin_[1] - 0.5 * f[1];
            }

            f[size_ - 1] = 1.5 * yBegin_[size_ - 1] - 0.5 * f[size_ - 2];

            if (forcePositive_)
            {
                if (f[0] < 0)
                {
                    f[0] = 0.0;
                }
                if (f[size_ - 1] < 0.0)
                {
                    f[size_ - 1] = 0.0;
                }
            }

            double primitive = 0.0;

            for (int i = 0; i < startPoint - 1; ++i)
            {
                primitive += yBegin_[i + 1] * (xBegin_[i + 1] - xBegin_[i]);
            }

            int endPoint = size_;

            //constantLastPeriod_ = false;
            if (constantLastPeriod_)
            {
                endPoint = endPoint - 1;
            }

            for (int i = startPoint; i < endPoint; ++i)
            {
                double gPrev = f[i - 1] - yBegin_[i];
                double gNext = f[i] - yBegin_[i];
                //first deal with the zero gradient case
                if (Math.Abs(gPrev) < 1.0E-14 && Math.Abs(gNext) < 1.0E-14)
                {
                    ISectionHelper singleHelper = new ConstantGradHelper(f[i - 1], primitive,
                                                                         xBegin_[i - 1],
                                                                         xBegin_[i],
                                                                         f[i]);
                    sectionHelpers_.Add(xBegin_[i], singleHelper);
                }
                else
                {
                    double         quadraticity       = quadraticity_;
                    ISectionHelper quadraticHelper    = null;
                    ISectionHelper convMonotoneHelper = null;
                    if (quadraticity_ > 0.0)
                    {
                        if (gPrev >= -2.0 * gNext && gPrev > -0.5 * gNext && forcePositive_)
                        {
                            quadraticHelper = new QuadraticMinHelper(xBegin_[i - 1],
                                                                     xBegin_[i],
                                                                     f[i - 1], f[i],
                                                                     yBegin_[i],
                                                                     primitive);
                        }
                        else
                        {
                            quadraticHelper = new QuadraticHelper(xBegin_[i - 1],
                                                                  xBegin_[i],
                                                                  f[i - 1], f[i],
                                                                  yBegin_[i],
                                                                  primitive);
                        }
                    }
                    if (quadraticity_ < 1.0)
                    {
                        if ((gPrev > 0.0 && -0.5 * gPrev >= gNext && gNext >= -2.0 * gPrev) ||
                            (gPrev < 0.0 && -0.5 * gPrev <= gNext && gNext <= -2.0 * gPrev))
                        {
                            quadraticity = 1.0;
                            if (quadraticity_ == 0)
                            {
                                if (forcePositive_)
                                {
                                    quadraticHelper = new QuadraticMinHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        f[i - 1], f[i],
                                        yBegin_[i],
                                        primitive);
                                }
                                else
                                {
                                    quadraticHelper = new QuadraticHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        f[i - 1], f[i],
                                        yBegin_[i],
                                        primitive);
                                }
                            }
                        }
                        else if ((gPrev < 0.0 && gNext > -2.0 * gPrev) ||
                                 (gPrev > 0.0 && gNext < -2.0 * gPrev))
                        {
                            double eta = (gNext + 2.0 * gPrev) / (gNext - gPrev);
                            double b2  = (1.0 + monotonicity_) / 2.0;
                            if (eta < b2)
                            {
                                convMonotoneHelper = new ConvexMonotone2Helper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                            else
                            {
                                if (forcePositive_)
                                {
                                    convMonotoneHelper = new ConvexMonotone4MinHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b2, primitive);
                                }
                                else
                                {
                                    convMonotoneHelper = new ConvexMonotone4Helper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b2, primitive);
                                }
                            }
                        }
                        else if ((gPrev > 0.0 && gNext < 0.0 && gNext > -0.5 * gPrev) ||
                                 (gPrev < 0.0 && gNext > 0.0 && gNext < -0.5 * gPrev))
                        {
                            double eta = gNext / (gNext - gPrev) * 3.0;
                            double b3  = (1.0 - monotonicity_) / 2.0;
                            if (eta > b3)
                            {
                                convMonotoneHelper = new ConvexMonotone3Helper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                            else
                            {
                                if (forcePositive_)
                                {
                                    convMonotoneHelper = new ConvexMonotone4MinHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b3, primitive);
                                }
                                else
                                {
                                    convMonotoneHelper = new ConvexMonotone4Helper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b3, primitive);
                                }
                            }
                        }
                        else
                        {
                            double eta = gNext / (gPrev + gNext);
                            double b2  = (1.0 + monotonicity_) / 2.0;
                            double b3  = (1.0 - monotonicity_) / 2.0;
                            if (eta > b2)
                            {
                                eta = b2;
                            }
                            if (eta < b3)
                            {
                                eta = b3;
                            }
                            if (forcePositive_)
                            {
                                convMonotoneHelper = new ConvexMonotone4MinHelper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                            else
                            {
                                convMonotoneHelper = new ConvexMonotone4Helper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                        }
                    }

                    if (quadraticity == 1.0)
                    {
                        sectionHelpers_.Add(xBegin_[i], quadraticHelper);
                    }
                    else if (quadraticity == 0.0)
                    {
                        sectionHelpers_.Add(xBegin_[i], convMonotoneHelper);
                    }
                    else
                    {
                        sectionHelpers_.Add(xBegin_[i], new ComboHelper(quadraticHelper, convMonotoneHelper, quadraticity));
                    }
                }
                primitive += yBegin_[i] * (xBegin_[i] - xBegin_[i - 1]);
            }

            if (constantLastPeriod_)
            {
                sectionHelpers_.Add(xBegin_[size_ - 1], new EverywhereConstantHelper(yBegin_[size_ - 1], primitive, xBegin_[size_ - 2]));
                extrapolationHelper_ = sectionHelpers_[xBegin_[size_ - 1]];
            }
            else
            {
                extrapolationHelper_ = new EverywhereConstantHelper((sectionHelpers_.Last()).Value.value(xBegin_.Last()),
                                                                    primitive, xBegin_.Last());
            }
        }
Пример #2
0
        public override void update()
        {
            sectionHelpers_.Clear();
            if (size_ == 2) { //single period
                ISectionHelper singleHelper = new EverywhereConstantHelper(yBegin_[1], 0.0, xBegin_[0]);
                sectionHelpers_.Add(xBegin_[1], singleHelper);
                extrapolationHelper_ = singleHelper;
                return;
            }

            List<double> f = new InitializedList<double>(size_);
            sectionHelpers_ = new Dictionary<double,ISectionHelper>(preSectionHelpers_);
            int startPoint = sectionHelpers_.Count+1;

            //first derive the boundary forwards.
            for (int i=startPoint; i<size_-1; ++i) {
                double dxPrev = xBegin_[i] - xBegin_[i-1];
                double dx = xBegin_[i+1] - xBegin_[i];
                f[i] = dxPrev/(dx+dxPrev) * yBegin_[i]
                     + dx/(dx+dxPrev) * yBegin_[i+1];
            }

            if (startPoint > 1)
                f[startPoint-1] = preSectionHelpers_.Last().Value.fNext();
            if (startPoint == 1)
                f[0] = 1.5 * yBegin_[1] - 0.5 * f[1];

            f[size_-1] = 1.5 * yBegin_[size_-1] - 0.5 * f[size_-2];

            if (forcePositive_) {
                if (f[0] < 0)
                    f[0] = 0.0;
                if (f[size_-1] < 0.0)
                    f[size_-1] = 0.0;
            }

            double primitive = 0.0;
            for (int i = 0; i < startPoint-1; ++i)
                primitive += yBegin_[i+1] * (xBegin_[i+1]-xBegin_[i]);

            int endPoint = size_;
            //constantLastPeriod_ = false;
            if (constantLastPeriod_)
                endPoint = endPoint-1;

            for (int i=startPoint; i< endPoint; ++i) {
                double gPrev = f[i-1] - yBegin_[i];
                double gNext = f[i] - yBegin_[i];
                //first deal with the zero gradient case
                if ( Math.Abs(gPrev) < 1.0E-14 && Math.Abs(gNext) < 1.0E-14 ) {
                    ISectionHelper singleHelper = new ConstantGradHelper(f[i - 1], primitive,
                                                            xBegin_[i-1],
                                                            xBegin_[i],
                                                            f[i]);
                    sectionHelpers_.Add(xBegin_[i], singleHelper);
                } else {
                    double quadraticity = quadraticity_;
                    ISectionHelper quadraticHelper = null;
                    ISectionHelper convMonotoneHelper = null;
                    if (quadraticity_ > 0.0) {
                        if (gPrev >= -2.0*gNext && gPrev > -0.5*gNext && forcePositive_) {
                            quadraticHelper = new QuadraticMinHelper(xBegin_[i-1],
                                                           xBegin_[i],
                                                           f[i-1], f[i],
                                                           yBegin_[i],
                                                           primitive);
                        } else {
                            quadraticHelper = new QuadraticHelper(xBegin_[i-1],
                                                        xBegin_[i],
                                                        f[i-1], f[i],
                                                        yBegin_[i],
                                                        primitive);
                        }
                    }
                    if (quadraticity_ < 1.0) {

                        if ((gPrev > 0.0 && -0.5*gPrev >= gNext && gNext >= -2.0*gPrev) ||
                            (gPrev < 0.0 && -0.5*gPrev <= gNext && gNext <= -2.0*gPrev)) {
                            quadraticity = 1.0;
                            if (quadraticity_ == 0) {
                                if (forcePositive_) {
                                    quadraticHelper = new QuadraticMinHelper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           f[i-1], f[i],
                                                           yBegin_[i],
                                                           primitive);
                                } else {
                                    quadraticHelper = new QuadraticHelper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           f[i-1], f[i],
                                                           yBegin_[i],
                                                           primitive);
                                }
                            }
                        }
                        else if ( (gPrev < 0.0 && gNext > -2.0*gPrev) ||
                                  (gPrev > 0.0 && gNext < -2.0*gPrev)) {

                            double eta = (gNext + 2.0*gPrev)/(gNext - gPrev);
                            double b2 = (1.0 + monotonicity_)/2.0;
                            if (eta < b2) {
                                convMonotoneHelper = new ConvexMonotone2Helper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           eta, primitive);
                            } else {
                                if (forcePositive_) {
                                    convMonotoneHelper = new ConvexMonotone4MinHelper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           b2, primitive);
                                } else {
                                    convMonotoneHelper = new ConvexMonotone4Helper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           b2, primitive);
                                }
                            }
                        }
                        else if ( (gPrev > 0.0 && gNext < 0.0 && gNext > -0.5*gPrev) ||
                                  (gPrev < 0.0 && gNext > 0.0 && gNext < -0.5*gPrev) ) {
                            double eta = gNext/(gNext-gPrev) * 3.0;
                            double b3 = (1.0 - monotonicity_) / 2.0;
                            if (eta > b3) {
                                convMonotoneHelper = new ConvexMonotone3Helper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           eta, primitive);
                            } else {
                                if (forcePositive_) {
                                    convMonotoneHelper = new ConvexMonotone4MinHelper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           b3, primitive);
                                } else {
                                    convMonotoneHelper = new ConvexMonotone4Helper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           b3, primitive);
                                }
                            }
                        } else {
                            double eta = gNext/(gPrev + gNext);
                            double b2 = (1.0 + monotonicity_) / 2.0;
                            double b3 = (1.0 - monotonicity_) / 2.0;
                            if (eta > b2)
                                eta = b2;
                            if (eta < b3)
                                eta = b3;
                            if (forcePositive_) {
                                convMonotoneHelper = new ConvexMonotone4MinHelper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           eta, primitive);
                            } else {
                                convMonotoneHelper = new ConvexMonotone4Helper(
                                                           xBegin_[i-1],
                                                           xBegin_[i],
                                                           gPrev, gNext,
                                                           yBegin_[i],
                                                           eta, primitive);
                            }
                        }
                    }

                    if (quadraticity == 1.0) {
                        sectionHelpers_.Add(xBegin_[i], quadraticHelper);
                    } else if (quadraticity == 0.0) {
                        sectionHelpers_.Add(xBegin_[i], convMonotoneHelper);
                    } else {
                        sectionHelpers_.Add(xBegin_[i], new ComboHelper(quadraticHelper, convMonotoneHelper, quadraticity));
                    }
                }
                primitive += yBegin_[i] * (xBegin_[i]-xBegin_[i-1]);
            }

            if (constantLastPeriod_) {
                sectionHelpers_.Add(xBegin_[size_-1], new EverywhereConstantHelper(yBegin_[size_-1], primitive, xBegin_[size_-2]));
                extrapolationHelper_ = sectionHelpers_[xBegin_[size_-1]];
            } else {
                extrapolationHelper_ = new EverywhereConstantHelper((sectionHelpers_.Last()).Value.value(xBegin_.Last()),
                                                                    primitive, xBegin_.Last());
            }
        }