/// <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); }
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(""); }
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); }
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); }
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); } }
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 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); }
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); }
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); }
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(""); }
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); }
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); }
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; } } } }