/// <summary> Uses nested Clenshaw-Curtis quadrature on the alternative form with an invariant to compute the probability that each element is the minimum for a set of normal distributions to within a user-specified precision </summary>
        /// <param name="distributions"> The set of normal distributions for which you want to compute P(X = min X) </param>
        /// <param name="errorTolerance"> The maximum total error in P(X = min X) over all regions </param>
        /// <param name="maxIterations"> The maximum number of times the quadrature rule will be used, doubling in order each time </param>
        /// <returns></returns>
        public static double[] ComplementsClenshawCurtisAutomatic(Normal[] distributions, double errorTolerance = 10E-14, int maxIterations = 10)
        {
            // Change integral to alternative form by negating the distributions
            distributions = NegateDistributions(distributions); // This change is local to this method

            // Compute the interval of integration
            double maxOfMeanMinus8Stddev = distributions[0].Mean - 8 * distributions[0].StdDev;
            double maxOfMeanPlus8Stddev  = distributions[0].Mean + 8 * distributions[0].StdDev;

            for (int i = 0; i < distributions.Length; i++)
            {
                maxOfMeanMinus8Stddev = Math.Max(maxOfMeanMinus8Stddev, distributions[i].Mean - 8 * distributions[i].StdDev);
                maxOfMeanPlus8Stddev  = Math.Max(maxOfMeanPlus8Stddev, distributions[i].Mean + 8 * distributions[i].StdDev);
            }
            // 8 standard deviations is just past the threshold beyond which normal PDFs are less than machine epsilon in double precision
            double intervalLowerLimit = maxOfMeanMinus8Stddev;
            double intervalUpperLimit = maxOfMeanPlus8Stddev;

            // Compute a linear transformation from that interval to [-1,1]
            double a = (intervalUpperLimit - intervalLowerLimit) / 2.0;
            //double b = -1 * (2 * intervalLowerLimit / (intervalUpperLimit - intervalLowerLimit) + 1); // TODO: Consider channging this to ILL + a, then z = az + b
            double b = intervalLowerLimit + a;

            //double xOfz(double z) => (z - b) * a; // As z ranges over [-1,1], x will range over [iLL,iUL]
            double xOfz(double z) => z * a + b; // As z ranges over [-1,1], x will range over [iLL,iUL]

            // --- Initialize the Vectors ---
            int    order    = 32; // Start with a 33-point CC rule
            double errorSum = double.PositiveInfinity;

            double[] errors      = new double[distributions.Length];
            double[] complements = new double[distributions.Length];
            double[] weights     = ClenshawCurtis.GetWeights(order);
            double[] X           = ClenshawCurtis.GetEvalPoints(order); // Eval points in Z
            for (int i = 0; i < X.Length; i++)
            {
                X[i] = xOfz(X[i]);
            }                                                     // Convert from Z to X
            double[] C          = new double[X.Length];           // The invariant product for each X value, without weights
            bool[]   isFinished = new bool[distributions.Length]; // Keeps track of which regions are already at the desired precision
            for (int i = 0; i < C.Length; i++)
            {
                C[i] = 1;
                for (int j = 0; j < distributions.Length; j++)
                {
                    C[i] *= distributions[j].CumulativeDistribution(X[i]);
                }
            }

            // --- Iterate higher order quadrature rules until desired precision is obtained ---
            for (int iteration = 0; iteration < maxIterations; iteration++)
            {
                // We will have three vectors X[], weights[], and C[] instead of two; the weights are now in weights[] instead of C[]
                // Each iteration replaces these vectors with expanded versions. Half + 1 of the entries are the old entries, and the other nearly half are freshly computed.
                // weights[] is the exception: it is completely replaced each time.

                double[] newComplements = new double[distributions.Length];

                // Update discard complement probability vector
                for (int i = 0; i < distributions.Length; i++)
                {
                    // Skip if this element is at the desired accuracy already
                    if (iteration > 1 && isFinished[i]) // errors[i] < errorTolerance / distributions.Length
                    {
                        newComplements[i] = complements[i];
                        continue;
                    }

                    newComplements[i] = 0;
                    for (int j = 0; j < C.Length; j++)
                    {
                        double CDFij = distributions[i].CumulativeDistribution(X[j]);
                        if (CDFij > 0)
                        {
                            newComplements[i] += distributions[i].Density(X[j]) * C[j] * weights[j] / CDFij;
                        }
                    }
                    newComplements[i] *= a; // Multiply by the derivative dx/dz
                }

                // Update the error
                if (iteration > 0)
                {
                    errorSum = 0;
                    for (int i = 0; i < errors.Length; i++)
                    {
                        double newError = Math.Abs(complements[i] - newComplements[i]);
                        // Detect if finished, which requires the error estimate for the ith term to be decreasing and less than its fair share of the total error tolerance
                        if (!isFinished[i] &&
                            i > 1 &&
                            newError < errorTolerance / distributions.Length &&
                            newError < errors[i])
                        {
                            isFinished[i] = true;
                        }
                        errors[i] = newError;
                        errorSum += errors[i];
                    }
                }
                complements = newComplements;

                // Determine if all regions appear to be finished refining their probability estimates
                //bool allRegionsFinished = false;
                //for (int i = 0; i < isFinished.Length; i++) { allRegionsFinished &= isFinished[i]; }

                // Check if all the probabilities add up to one
                double totalProb = 0;
                for (int i = 0; i < complements.Length; i++)
                {
                    totalProb += complements[i];
                }
                bool probsSumToOne = Math.Abs(totalProb - 1.0) < 1E-12;

                // Handle the end of the iteration
                if ((errorSum < errorTolerance && probsSumToOne /*&& allRegionsFinished*/) || iteration == maxIterations - 1)
                {
                    //Console.WriteLine($"Terminating on iteration {iteration} with remaining error estimate {errorSum}");
                    break; // Terminate and return complements
                }

                // Update the vectors for the next iteration
                order  *= 2;
                weights = ClenshawCurtis.GetWeights(order);
                // Stretch the old arrays so there are gaps for the new entries
                double[] newX = new double[weights.Length];
                double[] newC = new double[weights.Length];
                for (int i = 0; i < X.Length; i++)
                {
                    newX[2 * i] = X[i];
                    newC[2 * i] = C[i];
                }
                // Add the new entries to X
                double[] entries = ClenshawCurtis.GetOddEvalPoints(order); // New entries in Z
                for (int i = 0; i < entries.Length; i++)
                {
                    int slot = 2 * i + 1;
                    newX[slot] = xOfz(entries[i]); // Convert from Z to X
                    newC[slot] = 1;
                    for (int j = 0; j < distributions.Length; j++)
                    {
                        newC[slot] *= distributions[j].CumulativeDistribution(newX[slot]);
                    }
                }

                X = newX;
                C = newC;
            }

            return(complements);
        }
Пример #2
0
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for CLENSHAW_CURTIS_RULE.
    //
    //  Discussion:
    //
    //    This program computes a standard Clenshaw Curtis quadrature rule
    //    and writes it to a file.
    //
    //    The user specifies:
    //    * the ORDER (number of points) in the rule;
    //    * A, the left endpoint;
    //    * B, the right endpoint;
    //    * FILENAME, which defines the output filenames.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 February 2010
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        double a;
        double b;
        string filename;
        int    order;

        Console.WriteLine("");
        Console.WriteLine("CLENSHAW_CURTIS_RULE");
        Console.WriteLine("");
        Console.WriteLine("  Compute a Clenshaw Curtis rule for approximating");
        Console.WriteLine("");
        Console.WriteLine("    Integral ( -1 <= x <= +1 ) f(x) dx");
        Console.WriteLine("");
        Console.WriteLine("  of order ORDER.");
        Console.WriteLine("");
        Console.WriteLine("  The user specifies ORDER, A, B and FILENAME.");
        Console.WriteLine("");
        Console.WriteLine("  ORDER is the number of points.");
        Console.WriteLine("");
        Console.WriteLine("  A is the left endpoint.");
        Console.WriteLine("");
        Console.WriteLine("  B is the right endpoint.");
        Console.WriteLine("");
        Console.WriteLine("  FILENAME is used to generate 3 files:");
        Console.WriteLine("");
        Console.WriteLine("    filename_w.txt - the weight file");
        Console.WriteLine("    filename_x.txt - the abscissa file.");
        Console.WriteLine("    filename_r.txt - the region file.");
        //
        //  Get ORDER.
        //
        try
        {
            order = Convert.ToInt32(args[0]);
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the value of ORDER (1 or greater)");
            order = Convert.ToInt32(Console.ReadLine());
        }

        //
        //  Get A.
        //
        try
        {
            a = Convert.ToDouble(args[1]);
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the left endpoint A:");
            a = Convert.ToDouble(Console.ReadLine());
        }

        //
        //  Get B.
        //
        try
        {
            b = Convert.ToDouble(args[2]);
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the right endpoint B:");
            b = Convert.ToDouble(Console.ReadLine());
        }

        //
        //  Get FILENAME:
        //
        try
        {
            filename = args[3];
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter FILENAME, the \"root name\" of the quadrature files).");
            filename = Console.ReadLine();
        }

        //
        //  Input summary.
        //
        Console.WriteLine("");
        Console.WriteLine("  ORDER = " + order + "");
        Console.WriteLine("  A = " + a + "");
        Console.WriteLine("  B = " + b + "");
        Console.WriteLine("  FILENAME = \"" + filename + "\".");
        //
        //  Construct the rule.
        //
        double[] r = new double[2];
        double[] w = new double[order];
        double[] x = new double[order];

        r[0] = a;
        r[1] = b;

        ClenshawCurtis.clenshaw_curtis_compute(order, ref x, ref w);
        //
        //  Rescale the rule.
        //
        ClenshawCurtis.rescale(a, b, order, ref x, ref w);
        //
        //  Output the rule.
        //
        ClenshawCurtis.rule_write(order, filename, x, w, r);

        Console.WriteLine("");
        Console.WriteLine("CLENSHAW_CURTIS_RULE:");
        Console.WriteLine("  Normal end of execution.");

        Console.WriteLine("");
    }
Пример #3
0
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for PATTERSON_RULE.
    //
    //  Discussion:
    //
    //    This program computes a standard Gauss-Patterson quadrature rule
    //    and writes it to a file.
    //
    //  Usage:
    //
    //    patterson_rule order a b output
    //
    //    where
    //
    //    * ORDER is the number of points in the rule, and must be
    //      1, 3, 7, 15, 31, 63, 127, 255 or 511.
    //    * A is the left endpoint;
    //    * B is the right endpoint;
    //    * FILENAME is the "root name" of the output files.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 February 2010
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        double a;
        double b;
        string filename;
        int    order;

        Console.WriteLine("");
        Console.WriteLine("PATTERSON_RULE");
        Console.WriteLine("");
        Console.WriteLine("  Compute a Gauss-Patterson rule for approximating");
        Console.WriteLine("    Integral ( -1 <= x <= +1 ) f(x) dx");
        Console.WriteLine("  of order ORDER.");
        Console.WriteLine("");
        Console.WriteLine("  The user specifies ORDER, A, B, and FILENAME.");
        Console.WriteLine("");
        Console.WriteLine("  ORDER is 1, 3, 7, 15, 31, 63, 127, 255 or 511.");
        Console.WriteLine("  A is the left endpoint.");
        Console.WriteLine("  B is the right endpoint.");
        Console.WriteLine("  FILENAME is used to generate 3 files:");
        Console.WriteLine("    filename_w.txt - the weight file");
        Console.WriteLine("    filename_x.txt - the abscissa file.");
        Console.WriteLine("    filename_r.txt - the region file.");
        //
        //  Get ORDER.
        //
        try
        {
            order = Convert.ToInt32(args[0]);
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the value of ORDER.");
            order = Convert.ToInt32(Console.ReadLine());
        }

        if (!Order.order_check(order))
        {
            Console.WriteLine("");
            Console.WriteLine("PATTERSON_RULE:");
            Console.WriteLine("  ORDER is illegal.");
            Console.WriteLine("  Abnormal end of execution.");
            return;
        }

        //
        //  Get A.
        //
        try
        {
            a = Convert.ToDouble(args[1]);
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the left endpoint A:");
            a = Convert.ToDouble(Console.ReadLine());
        }

        //
        //  Get B.
        //
        try
        {
            b = Convert.ToDouble(args[2]);
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the right endpoint B:");
            b = Convert.ToDouble(Console.ReadLine());
        }

        //
        //  Get FILENAME:
        //
        try
        {
            filename = args[3];
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter FILENAME, the \"root name\" of the quadrature files).");
            filename = Console.ReadLine();
        }

        //
        //  Input summary.
        //
        Console.WriteLine("");
        Console.WriteLine("  ORDER = " + order + "");
        Console.WriteLine("  A = " + a + "");
        Console.WriteLine("  B = " + b + "");
        Console.WriteLine("  FILENAME = \"" + filename + "\".");
        //
        //  Construct the rule.
        //
        double[] r = new double[2];
        double[] w = new double[order];
        double[] x = new double[order];

        r[0] = a;
        r[1] = b;

        PattersonQuadrature.patterson_set(order, ref x, ref w);
        //
        //  Rescale the rule.
        //
        ClenshawCurtis.rescale(a, b, order, ref x, ref w);
        //
        //  Output the rule.
        //
        QuadratureRule.rule_write(order, filename, x, w, r);

        Console.WriteLine("");
        Console.WriteLine("PATTERSON_RULE:");
        Console.WriteLine("  Normal end of execution.");
        Console.WriteLine("");
    }
        public static double[] ComplementsClenshawCurtis(Normal[] distributions, int order)
        {
            // Change integral to alternative form by negating the distributions
            distributions = NegateDistributions(distributions); // This change is local to this method

            // Compute the evaluation points and weights
            double[] evalPoints = ClenshawCurtis.GetEvalPoints(order);
            double[] weights    = ClenshawCurtis.GetWeights(order);


            // Compute the interval of integration
            double maxMean  = distributions[0].Mean;
            double maxStdev = 0;

            for (int i = 0; i < distributions.Length; i++)
            {
                if (distributions[i].Mean > maxMean)
                {
                    maxMean = distributions[i].Mean;
                }
                if (distributions[i].StdDev > maxStdev)
                {
                    maxStdev = distributions[i].StdDev;
                }
            }
            // 8 standard deviations is just past the threshold beyond which normal PDFs are less than machine epsilon in double precision
            double intervalLowerLimit = maxMean - 8 * maxStdev;
            double intervalUpperLimit = maxMean + 8 * maxStdev;

            // Compute a linear transformation from that interval to [-1,1]
            double a = (intervalUpperLimit - intervalLowerLimit) / 2.0;
            double b = -1 * (2 * intervalLowerLimit / (intervalUpperLimit - intervalLowerLimit) + 1);

            double xOfz(double z) => (z - b) * a; // As z ranges over [-1,1], x will range over [iLL,iUL]

            // Compute the vector of constants
            double[] C = new double[evalPoints.Length];
            double[] X = new double[evalPoints.Length];
            for (int i = 0; i < C.Length; i++)
            {
                C[i] = weights[i];
                X[i] = xOfz(evalPoints[i]);
                for (int j = 0; j < distributions.Length; j++)
                {
                    C[i] *= distributions[j].CumulativeDistribution(X[i]);
                }
            }

            // --- Perform the Integration ---
            double[] complementProbs = new double[distributions.Length];
            for (int i = 0; i < distributions.Length; i++)
            {
                complementProbs[i] = 0;
                for (int j = 0; j < C.Length; j++)
                {
                    double CDFij = distributions[i].CumulativeDistribution(X[j]);
                    if (CDFij > 0)
                    {
                        complementProbs[i] += distributions[i].Density(X[j]) * C[j] / CDFij;
                    }
                }
                complementProbs[i] *= a; // Multiply by the derivative dx/dz
                Console.WriteLine($"CCAltInv[{i}]: {complementProbs[i]}");
            }

            return(complementProbs);
        }
Пример #5
0
    public static double[] product_weights(int dim_num, int[] order_1d, int order_nd, int rule)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    PRODUCT_WEIGHTS computes the weights of a product rule.
    //
    //  Discussion:
    //
    //    This routine computes the weights for a quadrature rule which is
    //    a product of closed rules of varying order.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 November 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int ORDER_1D[DIM_NUM], the order of the 1D rules.
    //
    //    Input, int ORDER_ND, the order of the product rule.
    //
    //    Input, int RULE, the index of the rule.
    //    1, "CC", Clenshaw Curtis Closed Fully Nested rule.
    //    2, "F1", Fejer 1 Open Fully Nested rule.
    //    3, "F2", Fejer 2 Open Fully Nested rule.
    //    4, "GP", Gauss Patterson Open Fully Nested rule.
    //    5, "GL", Gauss Legendre Open Weakly Nested rule.
    //    6, "GH", Gauss Hermite Open Weakly Nested rule.
    //    7, "LG", Gauss Laguerre Open Non Nested rule.
    //
    //    Output, double PRODUCT_WEIGHTS_CC[DIM_NUM*ORDER_ND],
    //    the product rule weights.
    //
    {
        int dim;
        int order;

        typeMethods.r8vecDPData data = new();

        double[] w_nd = new double[order_nd];

        for (order = 0; order < order_nd; order++)
        {
            w_nd[order] = 1.0;
        }

        for (dim = 0; dim < dim_num; dim++)
        {
            double[] w_1d;
            switch (rule)
            {
            case 1:
                w_1d = ClenshawCurtis.cc_weights(order_1d[dim]);
                break;

            case 2:
                w_1d = Fejer1.f1_weights(order_1d[dim]);
                break;

            case 3:
                w_1d = Fejer2.f2_weights(order_1d[dim]);
                break;

            case 4:
                w_1d = PattersonQuadrature.gp_weights(order_1d[dim]);
                break;

            case 5:
                w_1d = GaussQuadrature.gl_weights(order_1d[dim]);
                break;

            case 6:
                w_1d = GaussHermite.gh_weights(order_1d[dim]);
                break;

            case 7:
                w_1d = Legendre.QuadratureRule.lg_weights(order_1d[dim]);
                break;

            default:
                Console.WriteLine("");
                Console.WriteLine("PRODUCT_WEIGHTS - Fatal error!");
                Console.WriteLine("  Unrecognized rule number = " + rule + "");
                return(null);
            }

            typeMethods.r8vec_direct_product2(ref data, dim, order_1d[dim], w_1d, dim_num,
                                              order_nd, ref w_nd);
        }

        return(w_nd);
    }
Пример #6
0
    public static void product_mixed_growth_weight(int dim_num, int[] order_1d, int order_nd,
                                                   int[] rule, int[] np, double[] p,
                                                   Func <int, int, double[], double[], double[]>[] gw_compute_weights,
                                                   ref double[] weight_nd)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    PRODUCT_MIXED_GROWTH_WEIGHT computes the weights of a mixed product rule.
    //
    //  Discussion:
    //
    //    This routine computes the weights for a quadrature rule which is
    //    a product of 1D rules of varying order and kind.
    //
    //    The user must preallocate space for the output array WEIGHT_ND.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    20 June 2010
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int ORDER_1D[DIM_NUM], the order of the 1D rules.
    //
    //    Input, int ORDER_ND, the order of the product rule.
    //
    //    Input, int RULE[DIM_NUM], the rule in each dimension.
    //     1, "CC",  Clenshaw Curtis, Closed Fully Nested.
    //     2, "F2",  Fejer Type 2, Open Fully Nested.
    //     3, "GP",  Gauss Patterson, Open Fully Nested.
    //     4, "GL",  Gauss Legendre, Open Weakly Nested.
    //     5, "GH",  Gauss Hermite, Open Weakly Nested.
    //     6, "GGH", Generalized Gauss Hermite, Open Weakly Nested.
    //     7, "LG",  Gauss Laguerre, Open Non Nested.
    //     8, "GLG", Generalized Gauss Laguerre, Open Non Nested.
    //     9, "GJ",  Gauss Jacobi, Open Non Nested.
    //    10, "HGK", Hermite Genz-Keister, Open Fully Nested.
    //    11, "UO",  User supplied Open, presumably Non Nested.
    //    12, "UC",  User supplied Closed, presumably Non Nested.
    //
    //    Input, int NP[DIM_NUM], the number of parameters used by each rule.
    //
    //    Input, double P[sum(NP[*])], the parameters needed by each rule.
    //
    //    Input, void ( *GW_COMPUTE_WEIGHTS[] ) ( int order, int np, double p[], double w[] ),
    //    an array of pointers to functions which return the 1D quadrature weights
    //    associated with each spatial dimension for which a Golub Welsch rule
    //    is used.
    //
    //    Output, double WEIGHT_ND[ORDER_ND], the product rule weights.
    //
    {
        int dim;
        int i;

        typeMethods.r8vecDPData data = new();

        for (i = 0; i < order_nd; i++)
        {
            weight_nd[i] = 1.0;
        }

        int p_index = 0;

        for (dim = 0; dim < dim_num; dim++)
        {
            double[] weight_1d = new double[order_1d[dim]];

            switch (rule[dim])
            {
            case 1:
                ClenshawCurtis.clenshaw_curtis_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 2:
                Fejer2.fejer2_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 3:
                PattersonQuadrature.patterson_lookup_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 4:
                Legendre.QuadratureRule.legendre_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 5:
                HermiteQuadrature.hermite_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 6:
                HermiteQuadrature.gen_hermite_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 7:
                Laguerre.QuadratureRule.laguerre_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 8:
                Laguerre.QuadratureRule.gen_laguerre_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 9:
                JacobiQuadrature.jacobi_compute_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 10:
                HermiteQuadrature.hermite_genz_keister_lookup_weights_np(
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            case 11:
            case 12:
                gw_compute_weights[dim](
                    order_1d[dim], np[dim], p.Skip(+p_index).ToArray(), weight_1d);
                break;

            default:
                Console.WriteLine("");
                Console.WriteLine("PRODUCT_MIXED_GROWTH_WEIGHT - Fatal error!");
                Console.WriteLine("  Unexpected value of RULE[" + dim + "] = "
                                  + rule[dim] + ".");
                return;
            }

            p_index += np[dim];

            typeMethods.r8vec_direct_product2(ref data, dim, order_1d[dim], weight_1d,
                                              dim_num, order_nd, ref weight_nd);
        }
    }
Пример #7
0
    public static void sparse_grid_hermite_index(int dim_num, int level_max, int point_num,
                                                 ref int[] grid_index, ref int[] grid_base)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_HERMITE_INDEX indexes points in a Gauss-Hermite sparse grid.
    //
    //  Discussion:
    //
    //    The sparse grid is assumed to be formed from 1D Gauss-Hermite rules
    //    of ODD order, which have the property that only the central abscissa,
    //    X = 0.0, is "nested".
    //
    //    The necessary dimensions of GRID_INDEX can be determined by
    //    calling SPARSE_GRID_HERMITE_SIZE first.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 July 2008
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, the maximum value of LEVEL.
    //
    //    Input, int POINT_NUM, the total number of points in the grids.
    //
    //    Output, int GRID_INDEX[DIM_NUM*POINT_NUM], a list of
    //    point indices, representing a subset of the product grid of level
    //    LEVEL_MAX, representing (exactly once) each point that will show up in a
    //    sparse grid of level LEVEL_MAX.
    //
    //    Output, int GRID_BASE[DIM_NUM*POINT_NUM], a list of
    //    the orders of the Gauss-Hermite rules associated with each point
    //    and dimension.
    //
    {
        int level;
        //
        //  The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX.
        //
        int point_num2 = 0;

        int level_min = Math.Max(0, level_max + 1 - dim_num);

        int[] grid_base2 = new int[dim_num];
        int[] level_1d   = new int[dim_num];
        int[] order_1d   = new int[dim_num];

        for (level = level_min; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition LEVEL_1D(1:DIM_NUM)
            //  that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //
                ClenshawCurtis.level_to_order_open(dim_num, level_1d, ref order_1d);
                int dim;
                for (dim = 0; dim < dim_num; dim++)
                {
                    grid_base2[dim] = (order_1d[dim] - 1) / 2;
                }

                //
                //  The product of the 1D orders gives us the number of points in this grid.
                //
                int order_nd = typeMethods.i4vec_product(dim_num, order_1d);
                //
                //  The inner (hidden) loop generates all points corresponding to given grid.
                //
                int[] grid_index2 = Multigrid.multigrid_index_z(dim_num, order_1d, order_nd);
                //
                //  Determine the first level of appearance of each of the points.
                //  This allows us to flag certain points as being repeats of points
                //  generated on a grid of lower level.
                //
                //  This is SLIGHTLY tricky.
                //
                int[] grid_level = HermiteQuadrature.index_level_hermite(level, level_max, dim_num, order_nd,
                                                                         grid_index2, grid_base2);
                //
                //  Only keep those points which first appear on this level.
                //
                int point;
                for (point = 0; point < order_nd; point++)
                {
                    if (grid_level[point] != level)
                    {
                        continue;
                    }

                    for (dim = 0; dim < dim_num; dim++)
                    {
                        grid_index[dim + point_num2 * dim_num] =
                            grid_index2[dim + point * dim_num];
                        grid_base[dim + point_num2 * dim_num] = grid_base2[dim];
                    }

                    point_num2 += 1;
                }

                if (!more)
                {
                    break;
                }
            }
        }
    }
Пример #8
0
    public static double[] lagrange_interp_nd_value2(int m, int[] ind, double[] a, double[] b,
                                                     int nd, double[] zd, int ni, double[] xi)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    LAGRANGE_INTERP_ND_VALUE2 evaluates an ND Lagrange interpolant.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    30 September 2012
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, the spatial dimension.
    //
    //    Input, int IND[M], the index or level of the 1D rule
    //    to be used in each dimension.
    //
    //    Input, double A[M], B[M], the lower and upper limits.
    //
    //    Input, int ND, the number of points in the product grid.
    //
    //    Input, double ZD[ND], the function evaluated at the points XD.
    //
    //    Input, int NI, the number of points at which the
    //    interpolant is to be evaluated.
    //
    //    Input, double XI[M*NI], the points at which the interpolant
    //    is to be evaluated.
    //
    //    Output, double ZI[NI], the interpolant evaluated at the
    //    points XI.
    //
    {
        int j;

        typeMethods.r8vecDPData data = new();

        double[] w  = new double[nd];
        double[] zi = new double[ni];

        for (j = 0; j < ni; j++)
        {
            int i;
            for (i = 0; i < nd; i++)
            {
                w[i] = 1.0;
            }

            for (i = 0; i < m; i++)
            {
                int      n    = Order.order_from_level_135(ind[i]);
                double[] x_1d = ClenshawCurtis.cc_compute_points(n);
                int      k;
                for (k = 0; k < n; k++)
                {
                    x_1d[k] = 0.5 * ((1.0 - x_1d[k]) * a[i]
                                     + (1.0 + x_1d[k]) * b[i]);
                }

                double[] value = Lagrange1D.lagrange_base_1d(n, x_1d, 1, xi, xiIndex: +i + j * m);
                typeMethods.r8vec_direct_product2(ref data, i, n, value, m, nd, ref w);
            }

            zi[j] = typeMethods.r8vec_dot_product(nd, w, zd);
        }

        return(zi);
    }
    public static int[] sparse_grid_cc_index(int dim_num, int level_max, int point_num)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_CC_INDEX indexes the points forming a sparse grid.
    //
    //  Discussion:
    //
    //    The points forming the sparse grid are guaranteed to be a subset
    //    of a certain product grid.  The product grid is formed by DIM_NUM
    //    copies of a 1D rule of fixed order.  The orders of the 1D rule,
    //    (called ORDER_1D) and the order of the product grid, (called ORDER)
    //    are determined from the value LEVEL_MAX.
    //
    //    Thus, any point in the product grid can be identified by its grid index,
    //    a set of DIM_NUM indices, each between 1 and ORDER_1D.
    //
    //    This routine creates the GRID_INDEX array, listing (uniquely) the
    //    points of the sparse grid.
    //
    //    An assumption has been made that the 1D rule is closed (includes
    //    the interval endpoints) and nested (points that are part of a rule
    //    of a given level will be part of every rule of higher level).
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 November 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, the maximum value of LEVEL.
    //
    //    Input, int POINT_NUM, the total number of points in the grids.
    //
    //    Output, int SPARSE_GRID_CC_INDEX[DIM_NUM*POINT_NUM], a list of point
    //    indices, representing a subset of the product grid of level LEVEL_MAX,
    //    representing (exactly once) each point that will show up in a
    //    sparse grid of level LEVEL_MAX.
    //
    {
        int level;

        int[] grid_index = new int[dim_num * point_num];
        //
        //  The outer loop generates LEVELs from 0 to LEVEL_MAX.
        //
        int point_num2 = 0;

        int[] level_1d = new int[dim_num];
        int[] order_1d = new int[dim_num];

        for (level = 0; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition LEVEL_1D(1:DIM_NUM)
            //  that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //
                ClenshawCurtis.level_to_order_closed(dim_num, level_1d, ref order_1d);
                //
                //  The product of the 1D orders gives us the number of points in this grid.
                //
                int order_nd = typeMethods.i4vec_product(dim_num, order_1d);
                //
                //  The inner (hidden) loop generates all points corresponding to given grid.
                //
                int[] grid_index2 = Multigrid.multigrid_index0(dim_num, order_1d, order_nd);
                //
                //  Adjust these grid indices to reflect LEVEL_MAX.
                //
                Multigrid.multigrid_scale_closed(dim_num, order_nd, level_max, level_1d,
                                                 ref grid_index2);
                //
                //  Determine the first level of appearance of each of the points.
                //
                int[] grid_level = Abscissa.abscissa_level_closed_nd(level_max, dim_num, order_nd,
                                                                     grid_index2);
                //
                //  Only keep those points which first appear on this level.
                //
                int point;
                for (point = 0; point < order_nd; point++)
                {
                    if (grid_level[point] != level)
                    {
                        continue;
                    }

                    int dim;
                    for (dim = 0; dim < dim_num; dim++)
                    {
                        grid_index[dim + point_num2 * dim_num] =
                            grid_index2[dim + point * dim_num];
                    }

                    point_num2 += 1;
                }

                if (!more)
                {
                    break;
                }
            }
        }

        return(grid_index);
    }
Пример #10
0
    public static void sparse_grid_hermite(int dim_num, int level_max, int point_num,
                                           ref double[] grid_weight, ref double[] grid_point)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_HERMITE computes a sparse grid of Gauss-Hermite points.
    //
    //  Discussion:
    //
    //    The quadrature rule is associated with a sparse grid derived from
    //    a Smolyak construction using a 1D Gauss-Hermite quadrature rule.
    //
    //    The user specifies:
    //    * the spatial dimension of the quadrature region,
    //    * the level that defines the Smolyak grid.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 July 2008
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, controls the size of the final sparse grid.
    //
    //    Input, int POINT_NUM, the number of points in the grid, as determined
    //    by SPARSE_GRID_HERM_SIZE.
    //
    //    Output, double GRID_WEIGHT[POINT_NUM], the weights.
    //
    //    Output, double GRID_POINT[DIM_NUM*POINT_NUM], the points.
    //
    {
        int level;
        int point;
        int point3 = 0;

        for (point = 0; point < point_num; point++)
        {
            grid_weight[point] = 0.0;
        }

        //
        //  The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX.
        //
        int point_num2 = 0;

        int level_min = Math.Max(0, level_max + 1 - dim_num);

        int[] grid_base2 = new int[dim_num];
        int[] level_1d   = new int[dim_num];
        int[] order_1d   = new int[dim_num];

        for (level = level_min; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition LEVEL_1D(1:DIM_NUM)
            //  that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //  The relationship is the same as for other OPEN rules.
                //  The GL rule differs from the other OPEN rules only in the nesting behavior.
                //
                ClenshawCurtis.level_to_order_open(dim_num, level_1d, ref order_1d);

                int dim;
                for (dim = 0; dim < dim_num; dim++)
                {
                    grid_base2[dim] = (order_1d[dim] - 1) / 2;
                }

                //
                //  The product of the 1D orders gives us the number of points in this grid.
                //
                int order_nd = typeMethods.i4vec_product(dim_num, order_1d);
                //
                //  Compute the weights for this product grid.
                //
                double[] grid_weight2 = HermiteQuadrature.product_weight_hermite(dim_num, order_1d, order_nd);
                //
                //  Now determine the coefficient of the weight.
                //
                int coeff = (int)(Math.Pow(-1, level_max - level)
                                  * Binomial.choose(dim_num - 1, level_max - level));
                //
                //  The inner (hidden) loop generates all points corresponding to given grid.
                //  The grid indices will be between -M to +M, where 2*M + 1 = ORDER_1D(DIM).
                //
                int[] grid_index2 = Multigrid.multigrid_index_z(dim_num, order_1d, order_nd);
                //
                //  Determine the first level of appearance of each of the points.
                //  This allows us to flag certain points as being repeats of points
                //  generated on a grid of lower level.
                //
                //  This is SLIGHTLY tricky.
                //
                int[] grid_level = HermiteQuadrature.index_level_hermite(level, level_max, dim_num, order_nd,
                                                                         grid_index2, grid_base2);
                //
                //  Only keep those points which first appear on this level.
                //
                for (point = 0; point < order_nd; point++)
                {
                    //
                    //  Either a "new" point (increase count, create point, create weight)
                    //
                    if (grid_level[point] == level)
                    {
                        HermiteQuadrature.hermite_abscissa(dim_num, 1, grid_index2,
                                                           grid_base2, ref grid_point, gridIndex: +point * dim_num,
                                                           gridPointIndex: +point_num2 * dim_num);

                        grid_weight[point_num2] = coeff * grid_weight2[point];

                        point_num2 += 1;
                    }
                    //
                    //  or an already existing point (create point temporarily, find match,
                    //  add weight to matched point's weight).
                    //
                    else
                    {
                        double[] grid_point_temp = new double[dim_num];

                        HermiteQuadrature.hermite_abscissa(dim_num, 1, grid_index2,
                                                           grid_base2, ref grid_point_temp, gridIndex: +point * dim_num);

                        int point2;
                        for (point2 = 0; point2 < point_num2; point2++)
                        {
                            point3 = point2;
                            for (dim = 0; dim < dim_num; dim++)
                            {
                                if (!(Math.Abs(grid_point[dim + point2 * dim_num] - grid_point_temp[dim]) >
                                      double.Epsilon))
                                {
                                    continue;
                                }

                                point3 = -1;
                                break;
                            }

                            if (point3 == point2)
                            {
                                break;
                            }
                        }

                        switch (point3)
                        {
                        case -1:
                            Console.WriteLine("");
                            Console.WriteLine("SPARSE_GRID_HERM - Fatal error!");
                            Console.WriteLine("  Could not match point.");
                            return;

                        default:
                            grid_weight[point3] += coeff * grid_weight2[point];
                            break;
                        }
                    }
                }

                if (!more)
                {
                    break;
                }
            }
        }
    }
    public static void sparse_grid_cc_weights(int dim_num, int level_max, int point_num,
                                              int[] grid_index, ref double[] grid_weight)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_CC_WEIGHTS gathers the weights.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    12 March 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, the maximum value of LEVEL.
    //
    //    Input, int POINT_NUM, the total number of points in the grids.
    //
    //    Input, int GRID_INDEX[DIM_NUM*POINT_NUM], a list of point indices,
    //    representing a subset of the product grid of level LEVEL_MAX,
    //    representing (exactly once) each point that will show up in a
    //    sparse grid of level LEVEL_MAX.
    //
    //    Output, double GRID_WEIGHT[POINT_NUM], the weights
    //    associated with the sparse grid points.
    //
    {
        int level;
        int point;

        switch (level_max)
        {
        case 0:
        {
            for (point = 0; point < point_num; point++)
            {
                grid_weight[point] = Math.Pow(2.0, dim_num);
            }

            return;
        }
        }

        int[] level_1d = new int[dim_num];
        int[] order_1d = new int[dim_num];

        for (point = 0; point < point_num; point++)
        {
            grid_weight[point] = 0.0;
        }

        int level_min = Math.Max(0, level_max + 1 - dim_num);

        for (level = level_min; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition LEVEL_1D(1:DIM_NUM)
            //  that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //
                ClenshawCurtis.level_to_order_closed(dim_num, level_1d, ref order_1d);
                //
                //  The product of the 1D orders gives us the number of points in this grid.
                //
                int order_nd = typeMethods.i4vec_product(dim_num, order_1d);
                //
                //  Generate the indices of the points corresponding to the grid.
                //
                int[] grid_index2 = Multigrid.multigrid_index0(dim_num, order_1d, order_nd);
                //
                //  Compute the weights for this grid.
                //
                double[] grid_weight2 = ClenshawCurtis.product_weights_cc(dim_num, order_1d, order_nd);
                //
                //  Adjust the grid indices to reflect LEVEL_MAX.
                //
                Multigrid.multigrid_scale_closed(dim_num, order_nd, level_max, level_1d,
                                                 ref grid_index2);
                //
                //  Now determine the coefficient.
                //
                int coeff = typeMethods.i4_mop(level_max - level)
                            * typeMethods.i4_choose(dim_num - 1, level_max - level);

                int point2;
                for (point2 = 0; point2 < order_nd; point2++)
                {
                    bool found = false;

                    for (point = 0; point < point_num; point++)
                    {
                        bool all_equal = true;
                        int  dim;
                        for (dim = 0; dim < dim_num; dim++)
                        {
                            if (grid_index2[dim + point2 * dim_num] == grid_index[dim + point * dim_num])
                            {
                                continue;
                            }

                            all_equal = false;
                            break;
                        }

                        if (!all_equal)
                        {
                            continue;
                        }

                        grid_weight[point] += coeff * grid_weight2[point2];
                        found = true;
                        break;
                    }

                    switch (found)
                    {
                    case false:
                        Console.WriteLine("");
                        Console.WriteLine("SPARSE_GRID_CC_WEIGHTS - Fatal error!");
                        Console.WriteLine("  Could not find a match for a point.");
                        return;
                    }
                }

                if (!more)
                {
                    break;
                }
            }
        }
    }
    public static int sparse_grid_cc_size_old(int dim_num, int level_max)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_CC_SIZE_OLD sizes a sparse grid of Clenshaw Curtis points.
    //
    //  Discussion:
    //
    //    This function has been replaced by a new version which is much faster.
    //
    //    This version is retained for historical interest.
    //
    //    The grid is defined as the sum of the product rules whose LEVEL
    //    satisfies:
    //
    //      0 <= LEVEL <= LEVEL_MAX.
    //
    //    This routine works on an abstract set of nested grids.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 November 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, the maximum value of LEVEL.
    //
    //    Output, int SPARSE_GRID_CC_SIZE, the number of points in the grid.
    //
    {
        int level;
        int point_num;

        switch (level_max)
        {
        //
        //  Special case.
        //
        case 0:
            point_num = 1;
            return(point_num);
        }

        //
        //  The outer loop generates LEVELs from 0 to LEVEL_MAX.
        //
        point_num = 0;

        int[] level_1d = new int[dim_num];
        int[] order_1d = new int[dim_num];

        for (level = 0; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //
                ClenshawCurtis.level_to_order_closed(dim_num, level_1d, ref order_1d);
                //
                //  The product of the 1D orders gives us the number of points in this grid.
                //
                int order_nd = typeMethods.i4vec_product(dim_num, order_1d);
                //
                //  The inner (hidden) loop generates all points corresponding to given grid.
                //
                int[] grid_index = Multigrid.multigrid_index0(dim_num, order_1d, order_nd);
                //
                //  Adjust these grid indices to reflect LEVEL_MAX.
                //
                Multigrid.multigrid_scale_closed(dim_num, order_nd, level_max, level_1d,
                                                 ref grid_index);
                //
                //  Determine the first level of appearance of each of the points.
                //
                int[] grid_level = Abscissa.abscissa_level_closed_nd(level_max, dim_num, order_nd,
                                                                     grid_index);
                //
                //  Only keep those points which first appear on this level.
                //
                int point;
                for (point = 0; point < order_nd; point++)
                {
                    if (grid_level[point] == level)
                    {
                        point_num += 1;
                    }
                }

                if (!more)
                {
                    break;
                }
            }
        }

        return(point_num);
    }
Пример #13
0
    public static double[] lagrange_interp_nd_grid(int m, int[] n_1d, double[] a, double[] b,
                                                   int nd)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    LAGRANGE_INTERP_ND_GRID sets an M-dimensional Lagrange interpolant grid.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    30 September 2012
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, the spatial dimension.
    //
    //    Input, int N_1D[M], the order of the 1D rule to be used
    //    in each dimension.
    //
    //    Input, double A[M], B[M], the lower and upper limits.
    //
    //    Input, int ND, the number of points in the product grid.
    //
    //    Output, double LAGRANGE_INTERP_ND_GRID[M*ND], the points at which data
    //    is to be sampled.
    //
    {
        int i;
        int j;

        typeMethods.r8vecDPData data = new();
        //
        //  Compute the data points.
        //
        double[] xd = new double[m * nd];

        for (j = 0; j < nd; j++)
        {
            for (i = 0; i < m; i++)
            {
                xd[i + j * m] = 0.0;
            }
        }

        for (i = 0; i < m; i++)
        {
            int      n    = n_1d[i];
            double[] x_1d = ClenshawCurtis.cc_compute_points(n);
            for (j = 0; j < n; j++)
            {
                x_1d[j] = 0.5 * ((1.0 - x_1d[j]) * a[i]
                                 + (1.0 + x_1d[j]) * b[i]);
            }

            typeMethods.r8vec_direct_product(ref data, i, n, x_1d, m, nd, ref xd);
        }

        return(xd);
    }
Пример #14
0
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for CCN_RULE.
    //
    //  Discussion:
    //
    //    This program computes a nested Clenshaw Curtis quadrature rule
    //    and writes it to a file.
    //
    //    The user specifies:
    //    * N, the number of points in the rule;
    //    * A, the left endpoint;
    //    * B, the right endpoint;
    //    * FILENAME, which defines the output filenames.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    06 March 2011
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        double a;
        double b;
        string filename;
        int    n;

        Console.WriteLine("");
        Console.WriteLine("CCN_RULE");
        Console.WriteLine("  Compute one of a family of nested Clenshaw Curtis rules");
        Console.WriteLine("  for approximating");
        Console.WriteLine("    Integral ( -1 <= x <= +1 ) f(x) dx");
        Console.WriteLine("  of order N.");
        Console.WriteLine("");
        Console.WriteLine("  The user specifies N, A, B and FILENAME.");
        Console.WriteLine("");
        Console.WriteLine("  N is the number of points.");
        Console.WriteLine("  A is the left endpoint.");
        Console.WriteLine("  B is the right endpoint.");
        Console.WriteLine("  FILENAME is used to generate 3 files:");
        Console.WriteLine("    filename_w.txt - the weight file");
        Console.WriteLine("    filename_x.txt - the abscissa file.");
        Console.WriteLine("    filename_r.txt - the region file.");
        //
        //  Get N.
        //
        try
        {
            n = Convert.ToInt32(args[0]);
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the value of N (1 or greater)");
            string tmp = "";
            tmp = Console.ReadLine();
            n   = Convert.ToInt32(tmp);
        }

        //
        //  Get A.
        //
        try
        {
            a = Convert.ToInt32(args[1]);
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the left endpoint A:");
            string tmp = "";
            tmp = Console.ReadLine();
            a   = Convert.ToInt32(tmp);
        }

        //
        //  Get B.
        //
        try
        {
            b = Convert.ToInt32(args[2]);
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter the right endpoint B:");
            string tmp = "";
            tmp = Console.ReadLine();
            b   = Convert.ToInt32(tmp);
        }

        //
        //  Get FILENAME:
        //
        try
        {
            filename = args[3];
        }
        catch (Exception)
        {
            Console.WriteLine("");
            Console.WriteLine("  Enter FILENAME, the \"root name\" of the quadrature files.");
            filename = Console.ReadLine();
        }

        //
        //  Input summary.
        //
        Console.WriteLine("");
        Console.WriteLine("  N = " + n + "");
        Console.WriteLine("  A = " + a + "");
        Console.WriteLine("  B = " + b + "");
        Console.WriteLine("  FILENAME = \"" + filename + "\".");
        //
        //  Construct the rule.
        //
        double[] r = new double[2];

        r[0] = a;
        r[1] = b;

        double[] x = ClenshawCurtis.ccn_compute_points_new(n);

        const double x_min = -1.0;
        const double x_max = +1.0;

        double[] w = ClenshawCurtis.nc_compute_new(n, x_min, x_max, x);
        //
        //  Rescale the rule.
        //
        ClenshawCurtis.rescale(a, b, n, ref x, ref w);
        //
        //  Output the rule.
        //
        ClenshawCurtis.rule_write(n, filename, x, w, r);

        Console.WriteLine("");
        Console.WriteLine("CCN_RULE:");
        Console.WriteLine("  Normal end of execution.");
        Console.WriteLine("");
    }
Пример #15
0
    public static int sparse_grid_hermite_size(int dim_num, int level_max)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_HERMITE_SIZE sizes a sparse grid of Gauss-Hermite points.
    //
    //  Discussion:
    //
    //    The grid is defined as the sum of the product rules whose LEVEL
    //    satisfies:
    //
    //      LEVEL_MIN <= LEVEL <= LEVEL_MAX.
    //
    //    where LEVEL_MAX is user specified, and
    //
    //      LEVEL_MIN = max ( 0, LEVEL_MAX + 1 - DIM_NUM ).
    //
    //    The grids are only very weakly nested, since Gauss-Hermite rules
    //    only have the origin in common.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 July 2008
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, the maximum value of LEVEL.
    //
    //    Output, int SPARSE_GRID_HERM_SIZE, the number of points in the grid.
    //
    {
        int level;
        int point_num;

        switch (level_max)
        {
        //
        //  Special case.
        //
        case 0:
            point_num = 1;
            return(point_num);
        }

        //
        //  The outer loop generates LEVELs from 0 to LEVEL_MAX.
        //
        point_num = 0;

        int level_min = Math.Max(0, level_max + 1 - dim_num);

        int[] level_1d = new int[dim_num];
        int[] order_1d = new int[dim_num];

        for (level = level_min; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //
                ClenshawCurtis.level_to_order_open(dim_num, level_1d, ref order_1d);

                int dim;
                for (dim = 0; dim < dim_num; dim++)
                {
                    //
                    //  If we can reduce the level in this dimension by 1 and
                    //  still not go below LEVEL_MIN.
                    //
                    if (level_min < level && 1 < order_1d[dim])
                    {
                        order_1d[dim] -= 1;
                    }
                }

                point_num += typeMethods.i4vec_product(dim_num, order_1d);

                if (!more)
                {
                    break;
                }
            }
        }

        return(point_num);
    }
Пример #16
0
    public static int[] abscissa_level_closed_nd(int level_max, int dim_num, int test_num,
                                                 int[] test_val)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ABSCISSA_LEVEL_CLOSED_ND: first level at which an abscissa is generated.
    //
    //  Discussion:
    //
    //    We need this routine because the sparse grid is generated as a sum of
    //    product grids, and many points in the sparse grid will belong to several
    //    of these product grids, and we need to do something special the very
    //    first time we encounter such a point - namely, count it.  So this routine
    //    determines, for any point in the full product grid, the first level
    //    at which that point would be included.
    //
    //
    //    We assume an underlying product grid.  In each dimension, this product
    //    grid has order 2^LEVEL_MAX + 1.
    //
    //    We will say a sparse grid has total level LEVEL if each point in the
    //    grid has a total level of LEVEL or less.
    //
    //    The "level" of a point is determined as the sum of the levels of the
    //    point in each spatial dimension.
    //
    //    The level of a point in a single spatial dimension I is determined as
    //    the level, between 0 and LEVEL_MAX, at which the point's I'th index
    //    would have been generated.
    //
    //
    //    This description is terse and perhaps unenlightening.  Keep in mind
    //    that the product grid is the product of 1D grids,
    //    that the 1D grids are built up by levels, having
    //    orders (total number of points ) 1, 3, 5, 9, 17, 33 and so on,
    //    and that these 1D grids are nested, so that each point in a 1D grid
    //    has a first level at which it appears.
    //
    //    Our procedure for generating the points of a sparse grid, then, is
    //    to choose a value LEVEL_MAX, to generate the full product grid,
    //    but then only to keep those points on the full product grid whose
    //    LEVEL is less than or equal to LEVEL_MAX.
    //
    //
    //    Note that this routine is really just testing out the idea of
    //    determining the level.  Our true desire is to be able to start
    //    with a value LEVEL, and determine, in a straightforward manner,
    //    all the points that are generated exactly at that level, or
    //    all the points that are generated up to and including that level.
    //
    //    This allows us to generate the new points to be added to one sparse
    //    grid to get the next, or to generate a particular sparse grid at once.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 November 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int LEVEL_MAX, controls the size of the final sparse grid.
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int TEST_NUM, the number of points to be tested.
    //
    //    Input, int TEST_VAL[DIM_NUM*TEST_NUM], the indices of the points
    //    to be tested.  Normally, each index would be between 0 and 2^LEVEL_MAX.
    //
    //    Output, int ABSCISSA_LEVEL_ND[TEST_NUM], the value of LEVEL at which the
    //    point would first be generated, assuming that a standard sequence of
    //    nested grids is used.
    //
    {
        int j;

        int[] test_level = new int[test_num];

        switch (level_max)
        {
        case 0:
        {
            for (j = 0; j < test_num; j++)
            {
                test_level[j] = 0;
            }

            return(test_level);
        }
        }

        int order = (int)Math.Pow(2, level_max) + 1;

        for (j = 0; j < test_num; j++)
        {
            test_level[j] = ClenshawCurtis.index_to_level_closed(dim_num, test_val,
                                                                 order, level_max, tIndex: +j * dim_num);
        }

        return(test_level);
    }
Пример #17
0
    public static void sparse_grid_laguerre(int dim_num, int level_max, int point_num,
                                            ref double[] grid_weight, ref double[] grid_point)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SPARSE_GRID_LAGUERRE computes a sparse grid of Gauss-Laguerre points.
    //
    //  Discussion:
    //
    //    The quadrature rule is associated with a sparse grid derived from
    //    a Smolyak construction using a 1D Gauss-Laguerre quadrature rule.
    //
    //    The user specifies:
    //    * the spatial dimension of the quadrature region,
    //    * the level that defines the Smolyak grid.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 July 2008
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Fabio Nobile, Raul Tempone, Clayton Webster,
    //    A Sparse Grid Stochastic Collocation Method for Partial Differential
    //    Equations with Random Input Data,
    //    SIAM Journal on Numerical Analysis,
    //    Volume 46, Number 5, 2008, pages 2309-2345.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int LEVEL_MAX, controls the size of the final sparse grid.
    //
    //    Input, int POINT_NUM, the number of points in the grid, as determined
    //    by SPARSE_GRID_LAGUERRE_SIZE.
    //
    //    Output, double GRID_WEIGHT[POINT_NUM], the weights.
    //
    //    Output, double GRID_POINT[DIM_NUM*POINT_NUM], the points.
    //
    {
        int level;
        int point;

        for (point = 0; point < point_num; point++)
        {
            grid_weight[point] = 0.0;
        }

        //
        //  The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX.
        //
        int point_num2 = 0;

        int level_min = Math.Max(0, level_max + 1 - dim_num);

        int[] grid_base2 = new int[dim_num];
        int[] level_1d   = new int[dim_num];
        int[] order_1d   = new int[dim_num];

        for (level = level_min; level <= level_max; level++)
        {
            //
            //  The middle loop generates the next partition LEVEL_1D(1:DIM_NUM)
            //  that adds up to LEVEL.
            //
            bool more = false;
            int  h    = 0;
            int  t    = 0;

            for (;;)
            {
                Comp.comp_next(level, dim_num, ref level_1d, ref more, ref h, ref t);
                //
                //  Transform each 1D level to a corresponding 1D order.
                //  The relationship is the same as for other OPEN rules.
                //
                ClenshawCurtis.level_to_order_open(dim_num, level_1d, ref order_1d);

                int dim;
                for (dim = 0; dim < dim_num; dim++)
                {
                    grid_base2[dim] = order_1d[dim];
                }

                //
                //  The product of the 1D orders gives us the number of points in this grid.
                //
                int order_nd = typeMethods.i4vec_product(dim_num, order_1d);
                //
                //  Compute the weights for this product grid.
                //
                double[] grid_weight2 = QuadratureRule.product_weight_laguerre(dim_num, order_1d, order_nd);
                //
                //  Now determine the coefficient of the weight.
                //
                int coeff = (int)(Math.Pow(-1, level_max - level)
                                  * Binomial.choose(dim_num - 1, level_max - level));
                //
                //  The inner (hidden) loop generates all points corresponding to given grid.
                //  The grid indices will be between -M to +M, where 2*M + 1 = ORDER_1D(DIM).
                //
                int[] grid_index2 = Multigrid.multigrid_index_one(dim_num, order_1d, order_nd);

                for (point = 0; point < order_nd; point++)
                {
                    QuadratureRule.laguerre_abscissa(dim_num, 1, grid_index2,
                                                     grid_base2, ref grid_point, gridIndex: +point * dim_num,
                                                     gridPointIndex: +point_num2 * dim_num);

                    grid_weight[point_num2] = coeff * grid_weight2[point];

                    point_num2 += 1;
                }

                if (!more)
                {
                    break;
                }
            }
        }
    }