Exemple #1
0
        public color MultigridReduce(Action <Texture2D, RenderTarget2D> ReductionShader, bool Debug = false)
        {
            int n     = Multigrid[0].Width;
            int level = 0;

            while (n >= 2)
            {
                ReductionShader(Multigrid[level], Multigrid[level + 1]);

                if (Debug)
                {
                    Console.WriteLine($"Did multigrid reduce from level {level} to level {level + 1}, n == {n}");
                    Multigrid[level].CheckForNonZero();
                    var result = Multigrid[level + 1].CheckForNonZero();

                    if (n == 2 && result)
                    {
                        Console.WriteLine("Made it to the end of the line!");
                    }
                }

                n /= 2;
                level++;
            }
            GraphicsDevice.SetRenderTarget(null);

            Multigrid.Last().GetData(ReducedData);
            return((color)ReducedData[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;
                }
            }
        }
    }
    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 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);
    }
    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);
    }
Exemple #7
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;
                }
            }
        }
    }