# include # include # include # include # include # include using namespace std; # include "sandia_sparse.hpp" //****************************************************************************80 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 dim; int j; int order; int t; int *test_level; test_level = new int[test_num]; if ( level_max == 0 ) { for ( j = 0; j < test_num; j++ ) { test_level[j] = 0; } return test_level; } order = i4_power ( 2, level_max ) + 1; for ( j = 0; j < test_num; j++ ) { test_level[j] = index_to_level_closed ( dim_num, test_val+j*dim_num, order, level_max ); } return test_level; } //****************************************************************************80 int *abscissa_level_open_nd ( int level_max, int dim_num, int test_num, int test_val[] ) //****************************************************************************80 // // Purpose: // // ABSCISSA_LEVEL_OPEN_ND: first level at which given abscissa is generated. // // Discussion: // // We assume an underlying product grid. In each dimension, this product // grid has order 2**(LEVEL_MAX+1) - 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, 7, 15, 31 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. // // Modified: // // 19 April 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_OPEN_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 dim; int j; int level; int order; int t; int *test_level; test_level = new int[test_num]; if ( level_max == 0 ) { for ( j = 0; j < test_num; j++ ) { test_level[j] = 0; } return test_level; } order = i4_power ( 2, level_max ) + 1; for ( j = 0; j < test_num; j++ ) { test_level[j] = index_to_level_open ( dim_num, test_val+j*dim_num, order, level_max ); } return test_level; } //****************************************************************************80 double cc_abscissa ( int order, int i ) //****************************************************************************80 // // Purpose: // // CC_ABSCISSA returns the I-th abscissa of the Clenshaw Curtis rule. // // Discussion: // // Our convention is that the abscissas are numbered from left to // right. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 March 2008 // // Author: // // John Burkardt // // Parameters: // // Input, int ORDER, the order of the rule. // // Input, int I, the index of the desired abscissa. 1 <= I <= ORDER. // // Output, double CC_ABSCISSA, the value of the I-th // abscissa in the rule of order ORDER. // { double pi = 3.141592653589793; double value; if ( order < 1 ) { cout << "\n"; cout << "CC_ABSCISSA - Fatal error!\n"; cout << " Input value of ORDER < 1.\n"; cout << " Input value of ORDER = " << order << "\n"; exit ( 1 ); } if ( i < 1 || order < i ) { cout << "\n"; cout << "CC_ABSCISSA - Fatal error!\n"; cout << " 1 <= I <= ORDER is required.\n"; cout << " I = " << i << "\n"; cout << " ORDER = " << order << "\n"; exit ( 1 ); } if ( order == 1 ) { value = 0.0; } else if ( 2 * ( order - i ) == order - 1 ) { value = 0.0; } else { value = cos ( ( double ) ( order - i ) * pi / ( double ) ( order - 1 ) ); } return value; } //****************************************************************************80 double *cc_weights ( int n ) //****************************************************************************80 // // Purpose: // // CC_WEIGHTS computes Clenshaw Curtis weights. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 November 2007 // // Author: // // John Burkardt // // Reference: // // Charles Clenshaw, Alan Curtis, // A Method for Numerical Integration on an Automatic Computer, // Numerische Mathematik, // Volume 2, Number 1, December 1960, pages 197-205. // // Parameters: // // Input, int N, the order of the rule. // // Output, double CC_WEIGHTS[N], the weights of the rule. // { double b; int i; int j; double pi = 3.141592653589793; double theta; double *w; w = new double[n]; if ( n == 1 ) { w[0] = 2.0; return w; } for ( i = 1; i <= n; i++ ) { theta = ( double ) ( i - 1 ) * pi / ( double ) ( n - 1 ); w[i-1] = 1.0; for ( j = 1; j <= ( n - 1 ) / 2; j++ ) { if ( 2 * j == ( n - 1 ) ) { b = 1.0; } else { b = 2.0; } w[i-1] = w[i-1] - b * cos ( 2.0 * ( double ) ( j ) * theta ) / ( double ) ( 4 * j * j - 1 ); } } w[0] = w[0] / ( double ) ( n - 1 ); for ( i = 1; i < n-1; i++ ) { w[i] = 2.0 * w[i] / ( double ) ( n - 1 ); } w[n-1] = w[n-1] / ( double ) ( n - 1 ); return w; } //****************************************************************************80 void comp_next ( int n, int k, int a[], bool *more, int *h, int *t ) //****************************************************************************80 // // Purpose: // // COMP_NEXT computes the compositions of the integer N into K parts. // // Discussion: // // A composition of the integer N into K parts is an ordered sequence // of K nonnegative integers which sum to N. The compositions (1,2,1) // and (1,1,2) are considered to be distinct. // // The routine computes one composition on each call until there are no more. // For instance, one composition of 6 into 3 parts is // 3+2+1, another would be 6+0+0. // // On the first call to this routine, set MORE = FALSE. The routine // will compute the first element in the sequence of compositions, and // return it, as well as setting MORE = TRUE. If more compositions // are desired, call again, and again. Each time, the routine will // return with a new composition. // // However, when the LAST composition in the sequence is computed // and returned, the routine will reset MORE to FALSE, signaling that // the end of the sequence has been reached. // // This routine originally used a SAVE statement to maintain the // variables H and T. I have decided that it is safer // to pass these variables as arguments, even though the user should // never alter them. This allows this routine to safely shuffle // between several ongoing calculations. // // // There are 28 compositions of 6 into three parts. This routine will // produce those compositions in the following order: // // I A // - --------- // 1 6 0 0 // 2 5 1 0 // 3 4 2 0 // 4 3 3 0 // 5 2 4 0 // 6 1 5 0 // 7 0 6 0 // 8 5 0 1 // 9 4 1 1 // 10 3 2 1 // 11 2 3 1 // 12 1 4 1 // 13 0 5 1 // 14 4 0 2 // 15 3 1 2 // 16 2 2 2 // 17 1 3 2 // 18 0 4 2 // 19 3 0 3 // 20 2 1 3 // 21 1 2 3 // 22 0 3 3 // 23 2 0 4 // 24 1 1 4 // 25 0 2 4 // 26 1 0 5 // 27 0 1 5 // 28 0 0 6 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 July 2008 // // Author: // // Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. // C++ version by John Burkardt. // // Reference: // // Albert Nijenhuis, Herbert Wilf, // Combinatorial Algorithms for Computers and Calculators, // Second Edition, // Academic Press, 1978, // ISBN: 0-12-519260-6, // LC: QA164.N54. // // Parameters: // // Input, int N, the integer whose compositions are desired. // // Input, int K, the number of parts in the composition. // // Input/output, int A[K], the parts of the composition. // // Input/output, bool *MORE. // Set MORE = FALSE on first call. It will be reset to TRUE on return // with a new composition. Each new call returns another composition until // MORE is set to FALSE when the last composition has been computed // and returned. // // Input/output, int *H, *T, two internal parameters needed for the // computation. The user should allocate space for these in the calling // program, include them in the calling sequence, but never alter them! // { int i; if ( !( *more ) ) { *t = n; *h = 0; a[0] = n; for ( i = 1; i < k; i++ ) { a[i] = 0; } } else { if ( 1 < *t ) { *h = 0; } *h = *h + 1; *t = a[*h-1]; a[*h-1] = 0; a[0] = *t - 1; a[*h] = a[*h] + 1; } *more = ( a[k-1] != n ); return; } //****************************************************************************80 double f1_abscissa ( int order, int i ) //****************************************************************************80 // // Purpose: // // F1_ABSCISSA returns the I-th abscissa for the Fejer type 1 rule. // // Discussion: // // Our convention is that the abscissas are numbered from left to // right. // // This rule is defined on [-1,1]. // // Modified: // // 31 March 2008 // // Author: // // John Burkardt // // Parameters: // // Input, int ORDER, the order of the Fejer type 1 rule. // 1 <= ORDER. // // Input, int I, the index of the desired abscissa. // 1 <= I <= ORDER. // // Output, double F1_ABSCISSA, the value of the I-th // abscissa in the Fejer type 1 rule of order ORDER. // { double pi = 3.141592653589793; double value; if ( order < 1 ) { value = - r8_huge ( ); return value; } if ( i < 1 || order < i ) { cout << "\n"; cout << "F1_ABSCISSA - Fatal error!\n"; cout << " 1 <= I <= ORDER is required.\n"; cout << " I = " << i << "\n"; cout << " ORDER = " << order << "\n"; exit ( 1 ); } if ( order == 1 ) { value = 0.0; } else if ( 2 * ( 2 * order + 1 - 2 * i ) == 2 * order ) { value = 0.0; } else { value = cos ( ( double ) ( 2 * order + 1 - 2 * i ) * pi / ( double ) ( 2 * order ) ); } return value; } //****************************************************************************80 double *f1_weights ( int order ) //****************************************************************************80 // // Purpose: // // F1_WEIGHTS computes weights for a Fejer type 1 rule. // // Modified: // // 28 May 2007 // // Author: // // John Burkardt // // Reference: // // Philip Davis, Philip Rabinowitz, // Methods of Numerical Integration, // Second Edition, // Dover, 2007, // ISBN: 0486453391, // LC: QA299.3.D28. // // Walter Gautschi, // Numerical Quadrature in the Presence of a Singularity, // SIAM Journal on Numerical Analysis, // Volume 4, Number 3, 1967, pages 357-362. // // Joerg Waldvogel, // Fast Construction of the Fejer and Clenshaw-Curtis Quadrature Rules, // BIT Numerical Mathematics, // Volume 43, Number 1, 2003, pages 1-18. // // Parameters: // // Input, int ORDER, the order. // // Output, double F1_WEIGHTS[ORDER], the weights. // { int i; int j; double pi = 3.141592653589793; double *theta; double *w; if ( order < 1 ) { cout << "\n"; cout << "F1_WEIGHTS - Fatal error!\n"; cout << " ORDER < 1.\n"; exit ( 1 ); } w = new double[order]; if ( order == 1 ) { w[0] = 2.0; return w; } theta = new double[order]; for ( i = 1; i <= order; i++ ) { theta[i-1] = ( double ) ( 2 * ( order + 1 - i ) - 1 ) * pi / ( double ) ( 2 * order ); } for ( i = 1; i <= order; i++ ) { w[i-1] = 1.0; for ( j = 1; j <= ( order / 2 ); j++ ) { w[i-1] = w[i-1] - 2.0 * cos ( 2.0 * ( double ) ( j ) * theta[i-1] ) / ( double ) ( 4 * j * j - 1 ); } } for ( i = 0; i < order; i++ ) { w[i] = 2.0 * w[i] / ( double ) ( order ); } delete [] theta; return w; } //****************************************************************************80 double f2_abscissa ( int order, int i ) //****************************************************************************80 // // Purpose: // // F2_ABSCISSA returns the I-th abscissa for the Fejer type 2 rule. // // Discussion: // // Our convention is that the abscissas are numbered from left to // right. // // This rule is defined on [-1,1]. // // Modified: // // 31 March 2008 // // Author: // // John Burkardt // // Parameters: // // Input, int ORDER, the order of the Fejer type 2 rule. // 1 <= ORDER. // // Input, int I, the index of the desired abscissa. 1 <= I <= ORDER. // // Output, double F2_ABSCISSA, the value of the I-th // abscissa in the Fejer type 2 rule of order ORDER. // { double pi = 3.141592653589793; double value; if ( order < 1 ) { value = - r8_huge ( ); return value; } if ( i < 1 || order < i ) { cout << "\n"; cout << "F2_ABSCISSA - Fatal error!\n"; cout << " 1 <= I <= ORDER is required.\n"; cout << " I = " << i << "\n"; cout << " ORDER = " << order << "\n"; exit ( 1 ); } if ( order == 1 ) { value = 0.0; } else if ( 2 * ( order + 1 - i ) == order + 1 ) { value = 0.0; } else { value = cos ( ( double ) ( order + 1 - i ) * pi / ( double ) ( order + 1 ) ); } return value; } //****************************************************************************80 double *f2_weights ( int order ) //****************************************************************************80 // // Purpose: // // F2_WEIGHTS computes weights for a Fejer type 2 rule. // // Modified: // // 28 May 2007 // // Author: // // John Burkardt // // Reference: // // Philip Davis, Philip Rabinowitz, // Methods of Numerical Integration, // Second Edition, // Dover, 2007, // ISBN: 0486453391, // LC: QA299.3.D28. // // Walter Gautschi, // Numerical Quadrature in the Presence of a Singularity, // SIAM Journal on Numerical Analysis, // Volume 4, Number 3, 1967, pages 357-362. // // Joerg Waldvogel, // Fast Construction of the Fejer and Clenshaw-Curtis Quadrature Rules, // BIT Numerical Mathematics, // Volume 43, Number 1, 2003, pages 1-18. // // Parameters: // // Input, int ORDER, the order. // // Output, double F2_WEIGHTS[ORDER], the weights. // { int i; int j; double p; double pi = 3.141592653589793; double *theta; double *w; if ( order < 1 ) { cout << "\n"; cout << "F2_WEIGHTS - Fatal error!\n"; cout << " ORDER < 1.\n"; exit ( 1 ); } w = new double[order]; if ( order == 1 ) { w[0] = 2.0; return w; } else if ( order == 2 ) { w[0] = 1.0; w[1] = 1.0; return w; } theta = new double[order]; for ( i = 1; i <= order; i++ ) { theta[i-1] = ( double ) ( order + 1 - i ) * pi / ( double ) ( order + 1 ); } for ( i = 1; i <= order; i++ ) { w[i-1] = 1.0; for ( j = 1; j <= ( ( order - 1 ) / 2 ); j++ ) { w[i-1] = w[i-1] - 2.0 * cos ( 2.0 * ( double ) ( j ) * theta[i-1] ) / ( double ) ( 4 * j * j - 1 ); } if ( 2 < order ) { p = 2.0 * ( double ) ( ( ( order + 1 ) / 2 ) ) - 1.0; w[i-1] = w[i-1] - cos ( ( p + 1.0 ) * theta[i-1] ) / p; } } for ( i = 0; i < order; i++ ) { w[i] = 2.0 * w[i] / ( double ) ( order + 1 ); } delete [] theta; return w; } //****************************************************************************80 void gh_abscissa ( int dim_num, int point_num, int grid_index[], int grid_base[], double grid_point[] ) //****************************************************************************80 // // Purpose: // // GH_ABSCISSA sets abscissas for multidimensional Gauss-Hermite quadrature. // // Discussion: // // The "nesting" as it occurs for Gauss-Hermite sparse grids simply // involves the use of a specified set of permissible orders for the // rule. // // The X array lists the (complete) Gauss-Legendre abscissas for rules // of order 1, 3, 7, 15, 31, 63 or 127, in order. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 October 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the spatial dimension. // // Input, int POINT_NUM, the number of points. // // Input, int GRID_INDEX[DIM_NUM*POINT_NUM], the index of the abscissa // from the rule, for each dimension and point. // // Input, int GRID_BASE[DIM_NUM], the number of points used in the // rule for a given dimension. // // Output, double GRID_POINT[DIM_NUM], the grid points of abscissas. // { int dim; int level; int point; int pointer; int skip[8] = { 0, 1, 4, 11, 26, 57, 120, 247 }; double x[247] = { 0.0E+00, -0.122474487139158904909864203735E+01, 0.0E+00, 0.122474487139158904909864203735E+01, -0.265196135683523349244708200652E+01, -0.167355162876747144503180139830E+01, -0.816287882858964663038710959027E+00, 0.0E+00, 0.816287882858964663038710959027E+00, 0.167355162876747144503180139830E+01, 0.265196135683523349244708200652E+01, -0.449999070730939155366438053053E+01, -0.366995037340445253472922383312E+01, -0.296716692790560324848896036355E+01, -0.232573248617385774545404479449E+01, -0.171999257518648893241583152515E+01, -0.113611558521092066631913490556E+01, -0.565069583255575748526020337198E+00, 0.0E+00, 0.565069583255575748526020337198E+00, 0.113611558521092066631913490556E+01, 0.171999257518648893241583152515E+01, 0.232573248617385774545404479449E+01, 0.296716692790560324848896036355E+01, 0.366995037340445253472922383312E+01, 0.449999070730939155366438053053E+01, -6.9956801237185402753248521473232E+00, -6.2750787049428601427036567812530E+00, -5.6739614446185883296332558789276E+00, -5.1335955771123807045862968913996E+00, -4.6315595063128599420667997654336E+00, -4.1562717558181451724831352315314E+00, -3.7007434032314694224497164589673E+00, -3.2603207323135408104645401509648E+00, -2.8316804533902054557015640151425E+00, -2.4123177054804201051740184582119E+00, -2.0002585489356389657975562598571E+00, -1.5938858604721398261388419455550E+00, -1.1918269983500464260821358649242E+00, -0.79287697691530893968593032998830E+00, -0.39594273647142311094670041663436E+00, 0.0000000000000000000000000000000E+00, 0.39594273647142311094670041663436E+00, 0.79287697691530893968593032998830E+00, 1.1918269983500464260821358649242E+00, 1.5938858604721398261388419455550E+00, 2.0002585489356389657975562598571E+00, 2.4123177054804201051740184582119E+00, 2.8316804533902054557015640151425E+00, 3.2603207323135408104645401509648E+00, 3.7007434032314694224497164589673E+00, 4.1562717558181451724831352315314E+00, 4.6315595063128599420667997654336E+00, 5.1335955771123807045862968913996E+00, 5.6739614446185883296332558789276E+00, 6.2750787049428601427036567812530E+00, 6.9956801237185402753248521473232E+00, -10.435499877854168053468115427285E+00, -9.8028759912974963635223935286507E+00, -9.2792019543050391319404745506496E+00, -8.8118581437284546442526628275570E+00, -8.3807683451863219343010651043788E+00, -7.9755950801420373181541806298501E+00, -7.5901395198641066762479783194468E+00, -7.2203167078889678461161324222529E+00, -6.8632544331795368527353285876066E+00, -6.5168348106821160605273395854042E+00, -6.1794379922705969862418461787263E+00, -5.8497884000810673462526582961482E+00, -5.5268572526403031425047575122840E+00, -5.2097979830408354861575136416263E+00, -4.8979018644975742350745099214868E+00, -4.5905665744435190229271294569091E+00, -4.2872733352824404031727616199454E+00, -3.9875699104197157485227052068068E+00, -3.6910577000963465117322810559754E+00, -3.3973817713303911852755941806287E+00, -3.1062230279282566329138616746036E+00, -2.8172919672837977750747135657355E+00, -2.5303236304712010926855221718499E+00, -2.2450734604812066298995918179330E+00, -1.9613138583081485293922008411321E+00, -1.6788312791720137520802800622638E+00, -1.3974237486049625107570752063702E+00, -1.1168987050996462690510970277840E+00, -0.83707109558947615977737795461293E+00, -0.55776166427908221668763665253822E+00, -0.27879538567115223986687628627202E+00, 0.00000000000000000000000000000000E+00, 0.27879538567115223986687628627202E+00, 0.55776166427908221668763665253822E+00, 0.83707109558947615977737795461293E+00, 1.1168987050996462690510970277840E+00, 1.3974237486049625107570752063702E+00, 1.6788312791720137520802800622638E+00, 1.9613138583081485293922008411321E+00, 2.2450734604812066298995918179330E+00, 2.5303236304712010926855221718499E+00, 2.8172919672837977750747135657355E+00, 3.1062230279282566329138616746036E+00, 3.3973817713303911852755941806287E+00, 3.6910577000963465117322810559754E+00, 3.9875699104197157485227052068068E+00, 4.2872733352824404031727616199454E+00, 4.5905665744435190229271294569091E+00, 4.8979018644975742350745099214868E+00, 5.2097979830408354861575136416263E+00, 5.5268572526403031425047575122840E+00, 5.8497884000810673462526582961482E+00, 6.1794379922705969862418461787263E+00, 6.5168348106821160605273395854042E+00, 6.8632544331795368527353285876066E+00, 7.2203167078889678461161324222529E+00, 7.5901395198641066762479783194468E+00, 7.9755950801420373181541806298501E+00, 8.3807683451863219343010651043788E+00, 8.8118581437284546442526628275570E+00, 9.2792019543050391319404745506496E+00, 9.8028759912974963635223935286507E+00, 10.435499877854168053468115427285E+00, -15.228338148167350978246954433464E+00, -14.669595158833972632746354112896E+00, -14.209085995284870755168244250887E+00, -13.799722290211676634645246746673E+00, -13.423518590070950062438258321855E+00, -13.071208660474601901583995439649E+00, -12.737235652415686338138003924072E+00, -12.417939378869715805445879624069E+00, -12.110749020947747600132123508132E+00, -11.813772198267727195134584136191E+00, -11.525565112572696599167888588564E+00, -11.244994583785543445194384194300E+00, -10.971150569840247423423040263881E+00, -10.703288201027481347670940744690E+00, -10.440787957772772867742591798027E+00, -10.183127473450343888624126450357E+00, -9.9298610495114250736847004273684E+00, -9.6806044412474728038150712732737E+00, -9.4350233389881650135019598506287E+00, -9.1928244988460305715774195052527E+00, -8.9537488108565404323807890169970E+00, -8.7175658087076307363833999548548E+00, -8.4840692689832473326097180339984E+00, -8.2530736454457156579694124243888E+00, -8.0244111514703375578594739796798E+00, -7.7979293513870105420829120455591E+00, -7.5734891556083454022834960763301E+00, -7.3509631392269052701961258043733E+00, -7.1302341220350710668064025713431E+00, -6.9111939615465713197465633109366E+00, -6.6937425208758294190074417381666E+00, -6.4777867811645365448144903821487E+00, -6.2632400742737354345609723857092E+00, -6.0500214161419845694465474482388E+00, -5.8380549248774187386601690807757E+00, -5.6272693105464816659423455794909E+00, -5.4175974259243240722848425872924E+00, -5.2089758693153983587570258372239E+00, -5.0013446320386360038520809107373E+00, -4.7946467843764925009748509930857E+00, -4.5888281947698372951606485031212E+00, -4.3838372778464736294253744407459E+00, -4.1796247675352031349421189892408E+00, -3.9761435120673355916035814195920E+00, -3.7733482881250526721004678400057E+00, -3.5711956317782180447199756485249E+00, -3.3696436841717397896643629240035E+00, -3.1686520501953630191857798261495E+00, -2.9681816685955910267761649521505E+00, -2.7681946921824058801226545958892E+00, -2.5686543769473501723144013022363E+00, -2.3695249790490401080012474645702E+00, -2.1707716587411506879498498083695E+00, -1.9723603904195020079324743227565E+00, -1.7742578780516791584676442103681E+00, -1.5764314753267801315519597621879E+00, -1.3788491099261778091441557053728E+00, -1.1814792113700685848678583598423E+00, -0.98429064194027277726568984213773E+00, -0.78725263021825034151596831878971E+00, -0.59033470680942102142230439346102E+00, -0.39350664185130136568037826200185E+00, -0.19673838392423251964272239737078E+00, 0.0000000000000000000000000000000E+00, 0.19673838392423251964272239737078E+00, 0.39350664185130136568037826200185E+00, 0.59033470680942102142230439346102E+00, 0.78725263021825034151596831878971E+00, 0.98429064194027277726568984213773E+00, 1.1814792113700685848678583598423E+00, 1.3788491099261778091441557053728E+00, 1.5764314753267801315519597621879E+00, 1.7742578780516791584676442103681E+00, 1.9723603904195020079324743227565E+00, 2.1707716587411506879498498083695E+00, 2.3695249790490401080012474645702E+00, 2.5686543769473501723144013022363E+00, 2.7681946921824058801226545958892E+00, 2.9681816685955910267761649521505E+00, 3.1686520501953630191857798261495E+00, 3.3696436841717397896643629240035E+00, 3.5711956317782180447199756485249E+00, 3.7733482881250526721004678400057E+00, 3.9761435120673355916035814195920E+00, 4.1796247675352031349421189892408E+00, 4.3838372778464736294253744407459E+00, 4.5888281947698372951606485031212E+00, 4.7946467843764925009748509930857E+00, 5.0013446320386360038520809107373E+00, 5.2089758693153983587570258372239E+00, 5.4175974259243240722848425872924E+00, 5.6272693105464816659423455794909E+00, 5.8380549248774187386601690807757E+00, 6.0500214161419845694465474482388E+00, 6.2632400742737354345609723857092E+00, 6.4777867811645365448144903821487E+00, 6.6937425208758294190074417381666E+00, 6.9111939615465713197465633109366E+00, 7.1302341220350710668064025713431E+00, 7.3509631392269052701961258043733E+00, 7.5734891556083454022834960763301E+00, 7.7979293513870105420829120455591E+00, 8.0244111514703375578594739796798E+00, 8.2530736454457156579694124243888E+00, 8.4840692689832473326097180339984E+00, 8.7175658087076307363833999548548E+00, 8.9537488108565404323807890169970E+00, 9.1928244988460305715774195052527E+00, 9.4350233389881650135019598506287E+00, 9.6806044412474728038150712732737E+00, 9.9298610495114250736847004273684E+00, 10.183127473450343888624126450357E+00, 10.440787957772772867742591798027E+00, 10.703288201027481347670940744690E+00, 10.971150569840247423423040263881E+00, 11.244994583785543445194384194300E+00, 11.525565112572696599167888588564E+00, 11.813772198267727195134584136191E+00, 12.110749020947747600132123508132E+00, 12.417939378869715805445879624069E+00, 12.737235652415686338138003924072E+00, 13.071208660474601901583995439649E+00, 13.423518590070950062438258321855E+00, 13.799722290211676634645246746673E+00, 14.209085995284870755168244250887E+00, 14.669595158833972632746354112896E+00, 15.228338148167350978246954433464E+00 }; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_base[dim] < 0 ) { cout << "\n"; cout << "GH_ABSCISSA - Fatal error!\n"; cout << " Some base values are less than 0.\n"; exit ( 1 ); } } for ( dim = 0; dim < dim_num; dim++ ) { if ( 63 < grid_base[dim] ) { cout << "\n"; cout << "GH_ABSCISSA - Fatal error!\n"; cout << " Some base values are greater than 63.\n"; exit ( 1 ); } } for ( point = 0; point < point_num; point++ ) { for ( dim = 0; dim < dim_num; dim++ ) { level = i4_log_2 ( grid_base[dim] + 1 ); pointer = skip[level] + ( grid_index[dim+point*dim_num] + grid_base[dim] ); grid_point[dim+point*dim_num] = x[pointer]; } } return; } //****************************************************************************80 double *gh_weights ( int order ) //****************************************************************************80 // // Purpose: // // GH_WEIGHTS returns weights for certain Gauss-Hermite quadrature rules. // // Discussion: // // The allowed orders are 1, 3, 7, 15, 31, 63 and 127. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 07 October 2007 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Arthur Stroud, Don Secrest, // Gaussian Quadrature Formulas, // Prentice Hall, 1966, // LC: QA299.4G3S7. // // Parameters: // // Input, int ORDER, the order of the rule. // ORDER must be 1, 3, 7, 15, 31, 63 or 127. // // Output, double WEIGHT[ORDER], the weights. // The weights are positive, symmetric and should sum to SQRT(PI). // { double *weight; weight = new double[order]; if ( order == 1 ) { weight[1-1] = 1.77245385090551602729816748334E+00; } else if ( order == 3 ) { weight[1-1] = 0.295408975150919337883027913890E+00; weight[2-1] = 0.118163590060367735153211165556E+01; weight[3-1] = 0.295408975150919337883027913890E+00; } else if ( order == 7 ) { weight[1-1] = 0.971781245099519154149424255939E-03; weight[2-1] = 0.545155828191270305921785688417E-01; weight[3-1] = 0.425607252610127800520317466666E+00; weight[4-1] = 0.810264617556807326764876563813E+00; weight[5-1] = 0.425607252610127800520317466666E+00; weight[6-1] = 0.545155828191270305921785688417E-01; weight[7-1] = 0.971781245099519154149424255939E-03; } else if ( order == 15 ) { weight[1-1] = 0.152247580425351702016062666965E-08; weight[2-1] = 0.105911554771106663577520791055E-05; weight[3-1] = 0.100004441232499868127296736177E-03; weight[4-1] = 0.277806884291277589607887049229E-02; weight[5-1] = 0.307800338725460822286814158758E-01; weight[6-1] = 0.158488915795935746883839384960E+00; weight[7-1] = 0.412028687498898627025891079568E+00; weight[8-1] = 0.564100308726417532852625797340E+00; weight[9-1] = 0.412028687498898627025891079568E+00; weight[10-1] = 0.158488915795935746883839384960E+00; weight[11-1] = 0.307800338725460822286814158758E-01; weight[12-1] = 0.277806884291277589607887049229E-02; weight[13-1] = 0.100004441232499868127296736177E-03; weight[14-1] = 0.105911554771106663577520791055E-05; weight[15-1] = 0.152247580425351702016062666965E-08; } else if ( order == 31 ) { weight[ 1-1] = 0.46189683944498305857470556847735E-21; weight[ 2-1] = 0.51106090079112519643027197715274E-17; weight[ 3-1] = 0.58995564987355133075257722133966E-14; weight[ 4-1] = 0.18603735214463569590294465062239E-11; weight[ 5-1] = 0.23524920032013205739850619940094E-09; weight[ 6-1] = 0.14611988344865057576066495091513E-07; weight[ 7-1] = 0.50437125589241034841778074689627E-06; weight[ 8-1] = 0.10498602757642934202945441341697E-04; weight[ 9-1] = 0.13952090395003623854995664958146E-03; weight[ 10-1] = 0.12336833073030489880608311394968E-02; weight[ 11-1] = 0.74827999140119116765002499116934E-02; weight[ 12-1] = 0.31847230731201222775249585776902E-01; weight[ 13-1] = 0.96717948160569462991143316029341E-01; weight[ 14-1] = 0.21213278866810461318136114862419E+00; weight[ 15-1] = 0.33877265789305344906000174083214E+00; weight[ 16-1] = 0.39577855609737786462923720809676E+00; weight[ 17-1] = 0.33877265789305344906000174083214E+00; weight[ 18-1] = 0.21213278866810461318136114862419E+00; weight[ 19-1] = 0.96717948160569462991143316029341E-01; weight[ 20-1] = 0.31847230731201222775249585776902E-01; weight[ 21-1] = 0.74827999140119116765002499116934E-02; weight[ 22-1] = 0.12336833073030489880608311394968E-02; weight[ 23-1] = 0.13952090395003623854995664958146E-03; weight[ 24-1] = 0.10498602757642934202945441341697E-04; weight[ 25-1] = 0.50437125589241034841778074689627E-06; weight[ 26-1] = 0.14611988344865057576066495091513E-07; weight[ 27-1] = 0.23524920032013205739850619940094E-09; weight[ 28-1] = 0.18603735214463569590294465062239E-11; weight[ 29-1] = 0.58995564987355133075257722133966E-14; weight[ 30-1] = 0.51106090079112519643027197715274E-17; weight[ 31-1] = 0.46189683944498305857470556847735E-21; } else if ( order == 63 ) { weight[ 1-1] = 0.37099206434787551197827130470031E-47; weight[ 2-1] = 0.10400778615192299534481914814892E-41; weight[ 3-1] = 0.19796804708258311251124226474396E-37; weight[ 4-1] = 0.84687478191640015120141181138947E-34; weight[ 5-1] = 0.13071305930779945903630127634063E-30; weight[ 6-1] = 0.93437837175367456929765381518998E-28; weight[ 7-1] = 0.36027426635173044862245783257252E-25; weight[ 8-1] = 0.82963863115951789374753323156164E-23; weight[ 9-1] = 0.12266629909105281472971700203949E-20; weight[ 10-1] = 0.12288435628797061539461585325494E-18; weight[ 11-1] = 0.86925536958188009075932426691516E-17; weight[ 12-1] = 0.44857058689176221240330804981619E-15; weight[ 13-1] = 0.17335817955735154599902643794700E-13; weight[ 14-1] = 0.51265062385038307838565047455223E-12; weight[ 15-1] = 0.11808921844532942490513037158404E-10; weight[ 16-1] = 0.21508698297808025739828859845140E-09; weight[ 17-1] = 0.31371929535285447801497640621672E-08; weight[ 18-1] = 0.37041625984781705796752840204084E-07; weight[ 19-1] = 0.35734732949879669663960738150956E-06; weight[ 20-1] = 0.28393114498380927832990899215541E-05; weight[ 21-1] = 0.18709113003730498008961134765721E-04; weight[ 22-1] = 0.10284880800653635546698378640623E-03; weight[ 23-1] = 0.47411702610173128107201781718693E-03; weight[ 24-1] = 0.18409222622384813438539657470055E-02; weight[ 25-1] = 0.60436044551187631655712178246467E-02; weight[ 26-1] = 0.16829299199599730926458559757600E-01; weight[ 27-1] = 0.39858264027692992170237391875317E-01; weight[ 28-1] = 0.80467087993950415219587554532823E-01; weight[ 29-1] = 0.13871950817615293377792092082674E+00; weight[ 30-1] = 0.20448695346833761570957197160475E+00; weight[ 31-1] = 0.25799889943058042204920467417642E+00; weight[ 32-1] = 0.27876694884838411919175686949858E+00; weight[ 33-1] = 0.25799889943058042204920467417642E+00; weight[ 34-1] = 0.20448695346833761570957197160475E+00; weight[ 35-1] = 0.13871950817615293377792092082674E+00; weight[ 36-1] = 0.80467087993950415219587554532823E-01; weight[ 37-1] = 0.39858264027692992170237391875317E-01; weight[ 38-1] = 0.16829299199599730926458559757600E-01; weight[ 39-1] = 0.60436044551187631655712178246467E-02; weight[ 40-1] = 0.18409222622384813438539657470055E-02; weight[ 41-1] = 0.47411702610173128107201781718693E-03; weight[ 42-1] = 0.10284880800653635546698378640623E-03; weight[ 43-1] = 0.18709113003730498008961134765721E-04; weight[ 44-1] = 0.28393114498380927832990899215541E-05; weight[ 45-1] = 0.35734732949879669663960738150956E-06; weight[ 46-1] = 0.37041625984781705796752840204084E-07; weight[ 47-1] = 0.31371929535285447801497640621672E-08; weight[ 48-1] = 0.21508698297808025739828859845140E-09; weight[ 49-1] = 0.11808921844532942490513037158404E-10; weight[ 50-1] = 0.51265062385038307838565047455223E-12; weight[ 51-1] = 0.17335817955735154599902643794700E-13; weight[ 52-1] = 0.44857058689176221240330804981619E-15; weight[ 53-1] = 0.86925536958188009075932426691516E-17; weight[ 54-1] = 0.12288435628797061539461585325494E-18; weight[ 55-1] = 0.12266629909105281472971700203949E-20; weight[ 56-1] = 0.82963863115951789374753323156164E-23; weight[ 57-1] = 0.36027426635173044862245783257252E-25; weight[ 58-1] = 0.93437837175367456929765381518998E-28; weight[ 59-1] = 0.13071305930779945903630127634063E-30; weight[ 60-1] = 0.84687478191640015120141181138947E-34; weight[ 61-1] = 0.19796804708258311251124226474396E-37; weight[ 62-1] = 0.10400778615192299534481914814892E-41; weight[ 63-1] = 0.37099206434787551197827130470031E-47; } else if ( order == 127 ) { weight[ 1-1] = 0.12504497577050595552677230002883E-100; weight[ 2-1] = 0.17272798059419131415318615789672E-93; weight[ 3-1] = 0.89321681571986548608031150791499E-88; weight[ 4-1] = 0.77306185240893578449625186483810E-83; weight[ 5-1] = 0.20143957652648255497735460506196E-78; weight[ 6-1] = 0.21503714733610239701351039429345E-74; weight[ 7-1] = 0.11341924208594594813715533569504E-70; weight[ 8-1] = 0.33489139011795051950683388483136E-67; weight[ 9-1] = 0.60486548964016681064424451668405E-64; weight[ 10-1] = 0.71375092946352177824971347343892E-61; weight[ 11-1] = 0.57884563374885556636801095624030E-58; weight[ 12-1] = 0.33581166223858230300409326551248E-55; weight[ 13-1] = 0.14394641949253923568603163698953E-52; weight[ 14-1] = 0.46821808383216117724080263903889E-50; weight[ 15-1] = 0.11817054440684264071348471955361E-47; weight[ 16-1] = 0.23581659156008927203181682045005E-45; weight[ 17-1] = 0.37814427940797540210712758405540E-43; weight[ 18-1] = 0.49411031115771638145610738414006E-41; weight[ 19-1] = 0.53255303775425059266087298458297E-39; weight[ 20-1] = 0.47854390680131484999315199332765E-37; weight[ 21-1] = 0.36191883445952356128627543209554E-35; weight[ 22-1] = 0.23232083386343554805352497446119E-33; weight[ 23-1] = 0.12753331411008716683688974281454E-31; weight[ 24-1] = 0.60277753850758742112436095241270E-30; weight[ 25-1] = 0.24679773241777200207460855084439E-28; weight[ 26-1] = 0.88019567691698482573264198727415E-27; weight[ 27-1] = 0.27482489212040561315005725890593E-25; weight[ 28-1] = 0.75468218903085486125222816438456E-24; weight[ 29-1] = 0.18303134636280466270545996891835E-22; weight[ 30-1] = 0.39355990860860813085582448449811E-21; weight[ 31-1] = 0.75293161638581191068419292570042E-20; weight[ 32-1] = 0.12857997786722855037584105682618E-18; weight[ 33-1] = 0.19659326888445857792541925311450E-17; weight[ 34-1] = 0.26986511907214101894995783364250E-16; weight[ 35-1] = 0.33344414303198856330118301113874E-15; weight[ 36-1] = 0.37173303125150639885726463109574E-14; weight[ 37-1] = 0.37473954472839737091885387788983E-13; weight[ 38-1] = 0.34230094493397259538669512076007E-12; weight[ 39-1] = 0.28385303724993373166810860630552E-11; weight[ 40-1] = 0.21406920290454669208938772802828E-10; weight[ 41-1] = 0.14706331273431716244229273183839E-09; weight[ 42-1] = 0.92173940967434659264335883218167E-09; weight[ 43-1] = 0.52781663936972714041837056042506E-08; weight[ 44-1] = 0.27650497044951117835905283127679E-07; weight[ 45-1] = 0.13267855842539464770913063113371E-06; weight[ 46-1] = 0.58380944276113062188573331195042E-06; weight[ 47-1] = 0.23581561724775629112332165335800E-05; weight[ 48-1] = 0.87524468034280444703919485644809E-05; weight[ 49-1] = 0.29876790535909012274846532159647E-04; weight[ 50-1] = 0.93874435720072545206729594267039E-04; weight[ 51-1] = 0.27170762627931172053444716883938E-03; weight[ 52-1] = 0.72493929742498358979684249380921E-03; weight[ 53-1] = 0.17841208326763432884316727108264E-02; weight[ 54-1] = 0.40524855186046131499765636276283E-02; weight[ 55-1] = 0.85000263041544110385806705526917E-02; weight[ 56-1] = 0.16471142241609687824005585301760E-01; weight[ 57-1] = 0.29499296248213632269675010319119E-01; weight[ 58-1] = 0.48847387114300011006959603975676E-01; weight[ 59-1] = 0.74807989768583731416517226905270E-01; weight[ 60-1] = 0.10598520508090929403834368934301E+00; weight[ 61-1] = 0.13893945309051540832066283010510E+00; weight[ 62-1] = 0.16856236074207929740526975049765E+00; weight[ 63-1] = 0.18927849580120432177170145550076E+00; weight[ 64-1] = 0.19673340688823289786163676995151E+00; weight[ 65-1] = 0.18927849580120432177170145550076E+00; weight[ 66-1] = 0.16856236074207929740526975049765E+00; weight[ 67-1] = 0.13893945309051540832066283010510E+00; weight[ 68-1] = 0.10598520508090929403834368934301E+00; weight[ 69-1] = 0.74807989768583731416517226905270E-01; weight[ 70-1] = 0.48847387114300011006959603975676E-01; weight[ 71-1] = 0.29499296248213632269675010319119E-01; weight[ 72-1] = 0.16471142241609687824005585301760E-01; weight[ 73-1] = 0.85000263041544110385806705526917E-02; weight[ 74-1] = 0.40524855186046131499765636276283E-02; weight[ 75-1] = 0.17841208326763432884316727108264E-02; weight[ 76-1] = 0.72493929742498358979684249380921E-03; weight[ 77-1] = 0.27170762627931172053444716883938E-03; weight[ 78-1] = 0.93874435720072545206729594267039E-04; weight[ 79-1] = 0.29876790535909012274846532159647E-04; weight[ 80-1] = 0.87524468034280444703919485644809E-05; weight[ 81-1] = 0.23581561724775629112332165335800E-05; weight[ 82-1] = 0.58380944276113062188573331195042E-06; weight[ 83-1] = 0.13267855842539464770913063113371E-06; weight[ 84-1] = 0.27650497044951117835905283127679E-07; weight[ 85-1] = 0.52781663936972714041837056042506E-08; weight[ 86-1] = 0.92173940967434659264335883218167E-09; weight[ 87-1] = 0.14706331273431716244229273183839E-09; weight[ 88-1] = 0.21406920290454669208938772802828E-10; weight[ 89-1] = 0.28385303724993373166810860630552E-11; weight[ 90-1] = 0.34230094493397259538669512076007E-12; weight[ 91-1] = 0.37473954472839737091885387788983E-13; weight[ 92-1] = 0.37173303125150639885726463109574E-14; weight[ 93-1] = 0.33344414303198856330118301113874E-15; weight[ 94-1] = 0.26986511907214101894995783364250E-16; weight[ 95-1] = 0.19659326888445857792541925311450E-17; weight[ 96-1] = 0.12857997786722855037584105682618E-18; weight[ 97-1] = 0.75293161638581191068419292570042E-20; weight[ 98-1] = 0.39355990860860813085582448449811E-21; weight[ 99-1] = 0.18303134636280466270545996891835E-22; weight[100-1] = 0.75468218903085486125222816438456E-24; weight[101-1] = 0.27482489212040561315005725890593E-25; weight[102-1] = 0.88019567691698482573264198727415E-27; weight[103-1] = 0.24679773241777200207460855084439E-28; weight[104-1] = 0.60277753850758742112436095241270E-30; weight[105-1] = 0.12753331411008716683688974281454E-31; weight[106-1] = 0.23232083386343554805352497446119E-33; weight[107-1] = 0.36191883445952356128627543209554E-35; weight[108-1] = 0.47854390680131484999315199332765E-37; weight[109-1] = 0.53255303775425059266087298458297E-39; weight[110-1] = 0.49411031115771638145610738414006E-41; weight[111-1] = 0.37814427940797540210712758405540E-43; weight[112-1] = 0.23581659156008927203181682045005E-45; weight[113-1] = 0.11817054440684264071348471955361E-47; weight[114-1] = 0.46821808383216117724080263903889E-50; weight[115-1] = 0.14394641949253923568603163698953E-52; weight[116-1] = 0.33581166223858230300409326551248E-55; weight[117-1] = 0.57884563374885556636801095624030E-58; weight[118-1] = 0.71375092946352177824971347343892E-61; weight[119-1] = 0.60486548964016681064424451668405E-64; weight[120-1] = 0.33489139011795051950683388483136E-67; weight[121-1] = 0.11341924208594594813715533569504E-70; weight[122-1] = 0.21503714733610239701351039429345E-74; weight[123-1] = 0.20143957652648255497735460506196E-78; weight[124-1] = 0.77306185240893578449625186483810E-83; weight[125-1] = 0.89321681571986548608031150791499E-88; weight[126-1] = 0.17272798059419131415318615789672E-93; weight[127-1] = 0.12504497577050595552677230002883E-100; } else { cout << "\n"; cout << "GH_WEIGHTS - Fatal error!\n"; cout << " Illegal value of ORDER = " << order << "\n"; cout << " Legal values are 1, 3, 7, 15, 31, 63 and 127.\n"; exit ( 1 ); } return weight; } //****************************************************************************80 void gl_abscissa ( int dim_num, int point_num, int grid_index[], int grid_base[], double grid_point[] ) //****************************************************************************80 // // Purpose: // // GL_ABSCISSA sets abscissas for multidimensional Gauss-Legendre quadrature. // // Discussion: // // The "nesting" as it occurs for Gauss-Legendre sparse grids simply // involves the use of a specified set of permissible orders for the // rule. // // The X array lists the (complete) Gauss-Legendre abscissas for rules // of order 1, 3, 7, 15, 31, 63 or 127, in order. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 October 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the spatial dimension. // // Input, int POINT_NUM, the number of points. // // Input, int GRID_INDEX[DIM_NUM*POINT_NUM], the index of the abscissa // from the Gauss-Legendre rule, for each dimension and point. // // Input, int GRID_BASE[DIM_NUM], the number of points used in the // Gauss-Legendre rule for a given dimension. // // Output, double GRID_POINT[DIM_NUM], the grid points of // Gauss-Legendre abscissas. // { int dim; int level; int point; int pointer; int skip[8] = { 0, 1, 4, 11, 26, 57, 120, 247 }; double x[247] = { 0.0E+00, - 0.774596669241483377035853079956E+00, 0.0E+00, 0.774596669241483377035853079956E+00, - 0.949107912342758524526189684048E+00, - 0.741531185599394439863864773281E+00, - 0.405845151377397166906606412077E+00, 0.0E+00, 0.405845151377397166906606412077E+00, 0.741531185599394439863864773281E+00, 0.949107912342758524526189684048E+00, - 0.987992518020485428489565718587E+00, - 0.937273392400705904307758947710E+00, - 0.848206583410427216200648320774E+00, - 0.724417731360170047416186054614E+00, - 0.570972172608538847537226737254E+00, - 0.394151347077563369897207370981E+00, - 0.201194093997434522300628303395E+00, 0.0E+00, 0.201194093997434522300628303395E+00, 0.394151347077563369897207370981E+00, 0.570972172608538847537226737254E+00, 0.724417731360170047416186054614E+00, 0.848206583410427216200648320774E+00, 0.937273392400705904307758947710E+00, 0.987992518020485428489565718587E+00, -0.99708748181947707454263838179654, -0.98468590966515248400211329970113, -0.96250392509294966178905249675943, -0.93075699789664816495694576311725, -0.88976002994827104337419200908023, -0.83992032014626734008690453594388, -0.78173314841662494040636002019484, -0.71577678458685328390597086536649, -0.64270672292426034618441820323250, -0.56324916140714926272094492359516, -0.47819378204490248044059403935649, -0.38838590160823294306135146128752, -0.29471806998170161661790389767170, -0.19812119933557062877241299603283, -0.99555312152341520325174790118941E-01, 0.00000000000000000000000000000000, 0.99555312152341520325174790118941E-01, 0.19812119933557062877241299603283, 0.29471806998170161661790389767170, 0.38838590160823294306135146128752, 0.47819378204490248044059403935649, 0.56324916140714926272094492359516, 0.64270672292426034618441820323250, 0.71577678458685328390597086536649, 0.78173314841662494040636002019484, 0.83992032014626734008690453594388, 0.88976002994827104337419200908023, 0.93075699789664816495694576311725, 0.96250392509294966178905249675943, 0.98468590966515248400211329970113, 0.99708748181947707454263838179654, -0.99928298402912378050701628988630E+00, -0.99622401277797010860209018267357E+00, -0.99072854689218946681089469460884E+00, -0.98280881059372723486251140727639E+00, -0.97248403469757002280196067864927E+00, -0.95977944975894192707035416626398E+00, -0.94472613404100980296637531962798E+00, -0.92736092062184320544703138132518E+00, -0.90772630277853155803695313291596E+00, -0.88587032850785342629029845731337E+00, -0.86184648236412371953961183943106E+00, -0.83571355431950284347180776961571E+00, -0.80753549577345676005146598636324E+00, -0.77738126299037233556333018991104E+00, -0.74532464831784741782932166103759E+00, -0.71144409958484580785143153770401E+00, -0.67582252811498609013110331596954E+00, -0.63854710582136538500030695387338E+00, -0.59970905187762523573900892686880E+00, -0.55940340948628501326769780007005E+00, -0.51772881329003324812447758452632E+00, -0.47478724799480439992221230985149E+00, -0.43068379879511160066208893391863E+00, -0.38552639421224789247761502227440E+00, -0.33942554197458440246883443159432E+00, -0.29249405858625144003615715555067E+00, -0.24484679324595336274840459392483E+00, -0.19660034679150668455762745706572E+00, -0.14787278635787196856983909655297E+00, -0.98783356446945279529703669453922E-01, -0.49452187116159627234233818051808E-01, 0.00000000000000000000000000000000E+00, 0.49452187116159627234233818051808E-01, 0.98783356446945279529703669453922E-01, 0.14787278635787196856983909655297E+00, 0.19660034679150668455762745706572E+00, 0.24484679324595336274840459392483E+00, 0.29249405858625144003615715555067E+00, 0.33942554197458440246883443159432E+00, 0.38552639421224789247761502227440E+00, 0.43068379879511160066208893391863E+00, 0.47478724799480439992221230985149E+00, 0.51772881329003324812447758452632E+00, 0.55940340948628501326769780007005E+00, 0.59970905187762523573900892686880E+00, 0.63854710582136538500030695387338E+00, 0.67582252811498609013110331596954E+00, 0.71144409958484580785143153770401E+00, 0.74532464831784741782932166103759E+00, 0.77738126299037233556333018991104E+00, 0.80753549577345676005146598636324E+00, 0.83571355431950284347180776961571E+00, 0.86184648236412371953961183943106E+00, 0.88587032850785342629029845731337E+00, 0.90772630277853155803695313291596E+00, 0.92736092062184320544703138132518E+00, 0.94472613404100980296637531962798E+00, 0.95977944975894192707035416626398E+00, 0.97248403469757002280196067864927E+00, 0.98280881059372723486251140727639E+00, 0.99072854689218946681089469460884E+00, 0.99622401277797010860209018267357E+00, 0.99928298402912378050701628988630E+00 }; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_base[dim] < 0 ) { cout << "\n"; cout << "GL_ABSCISSA - Fatal error!\n"; cout << " Some base values are less than 0.\n"; exit ( 1 ); } } for ( dim = 0; dim < dim_num; dim++ ) { if ( 63 < grid_base[dim] ) { cout << "\n"; cout << "GL_ABSCISSA - Fatal error!\n"; cout << " Some base values are greater than 63.\n"; exit ( 1 ); } } for ( point = 0; point < point_num; point++ ) { for ( dim = 0; dim < dim_num; dim++ ) { level = i4_log_2 ( grid_base[dim] + 1 ); pointer = skip[level] + ( grid_index[dim+point*dim_num] + grid_base[dim] ); grid_point[dim+point*dim_num] = x[pointer]; } } return; } //****************************************************************************80 double *gl_weights ( int order ) //****************************************************************************80 // // Purpose: // // GL_WEIGHTS returns weights for certain Gauss-Legendre quadrature rules. // // Discussion: // // The allowed orders are 1, 3, 7, 15, 31, 63 and 127. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 October 2007 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Arthur Stroud, Don Secrest, // Gaussian Quadrature Formulas, // Prentice Hall, 1966, // LC: QA299.4G3S7. // // Parameters: // // Input, int ORDER, the order of the rule. // ORDER must be 1, 3, 7, 15, 31, 63 or 127. // // Output, double WEIGHT[ORDER], the weights. // The weights are positive, symmetric and should sum to 2. // { double *weight; weight = new double[order]; if ( order == 1 ) { weight[1-1] = 2.0E+00; } else if ( order == 3 ) { weight[1-1] = 5.0E+00 / 9.0E+00; weight[2-1] = 8.0E+00 / 9.0E+00; weight[3-1] = 5.0E+00 / 9.0E+00; } else if ( order == 7 ) { weight[1-1] = 0.129484966168869693270611432679E+00; weight[2-1] = 0.279705391489276667901467771424E+00; weight[3-1] = 0.381830050505118944950369775489E+00; weight[4-1] = 0.417959183673469387755102040816E+00; weight[5-1] = 0.381830050505118944950369775489E+00; weight[6-1] = 0.279705391489276667901467771424E+00; weight[7-1] = 0.129484966168869693270611432679E+00; } else if ( order == 15 ) { weight[1-1] = 0.307532419961172683546283935772E-01; weight[2-1] = 0.703660474881081247092674164507E-01; weight[3-1] = 0.107159220467171935011869546686E+00; weight[4-1] = 0.139570677926154314447804794511E+00; weight[5-1] = 0.166269205816993933553200860481E+00; weight[6-1] = 0.186161000015562211026800561866E+00; weight[7-1] = 0.198431485327111576456118326444E+00; weight[8-1] = 0.202578241925561272880620199968E+00; weight[9-1] = 0.198431485327111576456118326444E+00; weight[10-1] = 0.186161000015562211026800561866E+00; weight[11-1] = 0.166269205816993933553200860481E+00; weight[12-1] = 0.139570677926154314447804794511E+00; weight[13-1] = 0.107159220467171935011869546686E+00; weight[14-1] = 0.703660474881081247092674164507E-01; weight[15-1] = 0.307532419961172683546283935772E-01; } else if ( order == 31 ) { weight[ 1-1] = 0.74708315792487746093913218970494E-02; weight[ 2-1] = 0.17318620790310582463552990782414E-01; weight[ 3-1] = 0.27009019184979421800608642617676E-01; weight[ 4-1] = 0.36432273912385464024392008749009E-01; weight[ 5-1] = 0.45493707527201102902315857856518E-01; weight[ 6-1] = 0.54103082424916853711666259085477E-01; weight[ 7-1] = 0.62174786561028426910343543686657E-01; weight[ 8-1] = 0.69628583235410366167756126255124E-01; weight[ 9-1] = 0.76390386598776616426357674901331E-01; weight[10-1] = 0.82392991761589263903823367431962E-01; weight[11-1] = 0.87576740608477876126198069695333E-01; weight[12-1] = 0.91890113893641478215362871607150E-01; weight[13-1] = 0.95290242912319512807204197487597E-01; weight[14-1] = 0.97743335386328725093474010978997E-01; weight[15-1] = 0.99225011226672307874875514428615E-01; weight[16-1] = 0.99720544793426451427533833734349E-01; weight[17-1] = 0.99225011226672307874875514428615E-01; weight[18-1] = 0.97743335386328725093474010978997E-01; weight[19-1] = 0.95290242912319512807204197487597E-01; weight[20-1] = 0.91890113893641478215362871607150E-01; weight[21-1] = 0.87576740608477876126198069695333E-01; weight[22-1] = 0.82392991761589263903823367431962E-01; weight[23-1] = 0.76390386598776616426357674901331E-01; weight[24-1] = 0.69628583235410366167756126255124E-01; weight[25-1] = 0.62174786561028426910343543686657E-01; weight[26-1] = 0.54103082424916853711666259085477E-01; weight[27-1] = 0.45493707527201102902315857856518E-01; weight[28-1] = 0.36432273912385464024392008749009E-01; weight[29-1] = 0.27009019184979421800608642617676E-01; weight[30-1] = 0.17318620790310582463552990782414E-01; weight[31-1] = 0.74708315792487746093913218970494E-02; } else if ( order == 63 ) { weight[ 1-1] = 0.18398745955770837880499331680577E-02; weight[ 2-1] = 0.42785083468637618661951422543371E-02; weight[ 3-1] = 0.67102917659601362519069109850892E-02; weight[ 4-1] = 0.91259686763266563540586445877022E-02; weight[ 5-1] = 0.11519376076880041750750606118707E-01; weight[ 6-1] = 0.13884612616115610824866086365937E-01; weight[ 7-1] = 0.16215878410338338882283672974995E-01; weight[ 8-1] = 0.18507464460161270409260545805144E-01; weight[ 9-1] = 0.20753761258039090775341953421471E-01; weight[10-1] = 0.22949271004889933148942319561770E-01; weight[11-1] = 0.25088620553344986618630138068443E-01; weight[12-1] = 0.27166574359097933225189839439413E-01; weight[13-1] = 0.29178047208280526945551502154029E-01; weight[14-1] = 0.31118116622219817508215988557189E-01; weight[15-1] = 0.32982034883779341765683179672459E-01; weight[16-1] = 0.34765240645355877697180504642788E-01; weight[17-1] = 0.36463370085457289630452409787542E-01; weight[18-1] = 0.38072267584349556763638324927889E-01; weight[19-1] = 0.39587995891544093984807928149202E-01; weight[20-1] = 0.41006845759666398635110037009072E-01; weight[21-1] = 0.42325345020815822982505485403028E-01; weight[22-1] = 0.43540267083027590798964315704401E-01; weight[23-1] = 0.44648638825941395370332669516813E-01; weight[24-1] = 0.45647747876292608685885992608542E-01; weight[25-1] = 0.46535149245383696510395418746953E-01; weight[26-1] = 0.47308671312268919080604988338844E-01; weight[27-1] = 0.47966421137995131411052756195132E-01; weight[28-1] = 0.48506789097883847864090099145802E-01; weight[29-1] = 0.48928452820511989944709361549215E-01; weight[30-1] = 0.49230380423747560785043116988145E-01; weight[31-1] = 0.49411833039918178967039646116705E-01; weight[32-1] = 0.49472366623931020888669360420926E-01; weight[33-1] = 0.49411833039918178967039646116705E-01; weight[34-1] = 0.49230380423747560785043116988145E-01; weight[35-1] = 0.48928452820511989944709361549215E-01; weight[36-1] = 0.48506789097883847864090099145802E-01; weight[37-1] = 0.47966421137995131411052756195132E-01; weight[38-1] = 0.47308671312268919080604988338844E-01; weight[39-1] = 0.46535149245383696510395418746953E-01; weight[40-1] = 0.45647747876292608685885992608542E-01; weight[41-1] = 0.44648638825941395370332669516813E-01; weight[42-1] = 0.43540267083027590798964315704401E-01; weight[43-1] = 0.42325345020815822982505485403028E-01; weight[44-1] = 0.41006845759666398635110037009072E-01; weight[45-1] = 0.39587995891544093984807928149202E-01; weight[46-1] = 0.38072267584349556763638324927889E-01; weight[47-1] = 0.36463370085457289630452409787542E-01; weight[48-1] = 0.34765240645355877697180504642788E-01; weight[49-1] = 0.32982034883779341765683179672459E-01; weight[50-1] = 0.31118116622219817508215988557189E-01; weight[51-1] = 0.29178047208280526945551502154029E-01; weight[52-1] = 0.27166574359097933225189839439413E-01; weight[53-1] = 0.25088620553344986618630138068443E-01; weight[54-1] = 0.22949271004889933148942319561770E-01; weight[55-1] = 0.20753761258039090775341953421471E-01; weight[56-1] = 0.18507464460161270409260545805144E-01; weight[57-1] = 0.16215878410338338882283672974995E-01; weight[58-1] = 0.13884612616115610824866086365937E-01; weight[59-1] = 0.11519376076880041750750606118707E-01; weight[60-1] = 0.91259686763266563540586445877022E-02; weight[61-1] = 0.67102917659601362519069109850892E-02; weight[62-1] = 0.42785083468637618661951422543371E-02; weight[63-1] = 0.18398745955770837880499331680577E-02; } else if ( order == 127 ) { weight[ 1-1] = 0.45645726109586654495731936146574E-03; weight[ 2-1] = 0.10622766869538486959954760554099E-02; weight[ 3-1] = 0.16683488125171936761028811985672E-02; weight[ 4-1] = 0.22734860707492547802810838362671E-02; weight[ 5-1] = 0.28772587656289004082883197417581E-02; weight[ 6-1] = 0.34792893810051465908910894094105E-02; weight[ 7-1] = 0.40792095178254605327114733456293E-02; weight[ 8-1] = 0.46766539777779034772638165662478E-02; weight[ 9-1] = 0.52712596565634400891303815906251E-02; weight[ 10-1] = 0.58626653903523901033648343751367E-02; weight[ 11-1] = 0.64505120486899171845442463868748E-02; weight[ 12-1] = 0.70344427036681608755685893032552E-02; weight[ 13-1] = 0.76141028256526859356393930849227E-02; weight[ 14-1] = 0.81891404887415730817235884718726E-02; weight[ 15-1] = 0.87592065795403145773316804234385E-02; weight[ 16-1] = 0.93239550065309714787536985834029E-02; weight[ 17-1] = 0.98830429087554914716648010899606E-02; weight[ 18-1] = 0.10436130863141005225673171997668E-01; weight[ 19-1] = 0.10982883090068975788799657376065E-01; weight[ 20-1] = 0.11522967656921087154811609734510E-01; weight[ 21-1] = 0.12056056679400848183529562144697E-01; weight[ 22-1] = 0.12581826520465013101514365424172E-01; weight[ 23-1] = 0.13099957986718627426172681912499E-01; weight[ 24-1] = 0.13610136522139249906034237533759E-01; weight[ 25-1] = 0.14112052399003395774044161633613E-01; weight[ 26-1] = 0.14605400905893418351737288078952E-01; weight[ 27-1] = 0.15089882532666922992635733981431E-01; weight[ 28-1] = 0.15565203152273955098532590262975E-01; weight[ 29-1] = 0.16031074199309941802254151842763E-01; weight[ 30-1] = 0.16487212845194879399346060358146E-01; weight[ 31-1] = 0.16933342169871654545878815295200E-01; weight[ 32-1] = 0.17369191329918731922164721250350E-01; weight[ 33-1] = 0.17794495722974774231027912900351E-01; weight[ 34-1] = 0.18208997148375106468721469154479E-01; weight[ 35-1] = 0.18612443963902310429440419898958E-01; weight[ 36-1] = 0.19004591238555646611148901044533E-01; weight[ 37-1] = 0.19385200901246454628112623489471E-01; weight[ 38-1] = 0.19754041885329183081815217323169E-01; weight[ 39-1] = 0.20110890268880247225644623956287E-01; weight[ 40-1] = 0.20455529410639508279497065713301E-01; weight[ 41-1] = 0.20787750081531811812652137291250E-01; weight[ 42-1] = 0.21107350591688713643523847921658E-01; weight[ 43-1] = 0.21414136912893259295449693233545E-01; weight[ 44-1] = 0.21707922796373466052301324695331E-01; weight[ 45-1] = 0.21988529885872983756478409758807E-01; weight[ 46-1] = 0.22255787825930280235631416460158E-01; weight[ 47-1] = 0.22509534365300608085694429903050E-01; weight[ 48-1] = 0.22749615455457959852242553240982E-01; weight[ 49-1] = 0.22975885344117206754377437838947E-01; weight[ 50-1] = 0.23188206663719640249922582981729E-01; weight[ 51-1] = 0.23386450514828194170722043496950E-01; weight[ 52-1] = 0.23570496544381716050033676844306E-01; weight[ 53-1] = 0.23740233018760777777714726703424E-01; weight[ 54-1] = 0.23895556891620665983864481754172E-01; weight[ 55-1] = 0.24036373866450369675132086026456E-01; weight[ 56-1] = 0.24162598453819584716522917710986E-01; weight[ 57-1] = 0.24274154023278979833195063936748E-01; weight[ 58-1] = 0.24370972849882214952813561907241E-01; weight[ 59-1] = 0.24452996155301467956140198471529E-01; weight[ 60-1] = 0.24520174143511508275183033290175E-01; weight[ 61-1] = 0.24572466031020653286354137335186E-01; weight[ 62-1] = 0.24609840071630254092545634003360E-01; weight[ 63-1] = 0.24632273575707679066033370218017E-01; weight[ 64-1] = 0.24639752923961094419579417477503E-01; weight[ 65-1] = 0.24632273575707679066033370218017E-01; weight[ 66-1] = 0.24609840071630254092545634003360E-01; weight[ 67-1] = 0.24572466031020653286354137335186E-01; weight[ 68-1] = 0.24520174143511508275183033290175E-01; weight[ 69-1] = 0.24452996155301467956140198471529E-01; weight[ 70-1] = 0.24370972849882214952813561907241E-01; weight[ 71-1] = 0.24274154023278979833195063936748E-01; weight[ 72-1] = 0.24162598453819584716522917710986E-01; weight[ 73-1] = 0.24036373866450369675132086026456E-01; weight[ 74-1] = 0.23895556891620665983864481754172E-01; weight[ 75-1] = 0.23740233018760777777714726703424E-01; weight[ 76-1] = 0.23570496544381716050033676844306E-01; weight[ 77-1] = 0.23386450514828194170722043496950E-01; weight[ 78-1] = 0.23188206663719640249922582981729E-01; weight[ 79-1] = 0.22975885344117206754377437838947E-01; weight[ 80-1] = 0.22749615455457959852242553240982E-01; weight[ 81-1] = 0.22509534365300608085694429903050E-01; weight[ 82-1] = 0.22255787825930280235631416460158E-01; weight[ 83-1] = 0.21988529885872983756478409758807E-01; weight[ 84-1] = 0.21707922796373466052301324695331E-01; weight[ 85-1] = 0.21414136912893259295449693233545E-01; weight[ 86-1] = 0.21107350591688713643523847921658E-01; weight[ 87-1] = 0.20787750081531811812652137291250E-01; weight[ 88-1] = 0.20455529410639508279497065713301E-01; weight[ 89-1] = 0.20110890268880247225644623956287E-01; weight[ 90-1] = 0.19754041885329183081815217323169E-01; weight[ 91-1] = 0.19385200901246454628112623489471E-01; weight[ 92-1] = 0.19004591238555646611148901044533E-01; weight[ 93-1] = 0.18612443963902310429440419898958E-01; weight[ 94-1] = 0.18208997148375106468721469154479E-01; weight[ 95-1] = 0.17794495722974774231027912900351E-01; weight[ 96-1] = 0.17369191329918731922164721250350E-01; weight[ 97-1] = 0.16933342169871654545878815295200E-01; weight[ 98-1] = 0.16487212845194879399346060358146E-01; weight[ 99-1] = 0.16031074199309941802254151842763E-01; weight[100-1] = 0.15565203152273955098532590262975E-01; weight[101-1] = 0.15089882532666922992635733981431E-01; weight[102-1] = 0.14605400905893418351737288078952E-01; weight[103-1] = 0.14112052399003395774044161633613E-01; weight[104-1] = 0.13610136522139249906034237533759E-01; weight[105-1] = 0.13099957986718627426172681912499E-01; weight[106-1] = 0.12581826520465013101514365424172E-01; weight[107-1] = 0.12056056679400848183529562144697E-01; weight[108-1] = 0.11522967656921087154811609734510E-01; weight[109-1] = 0.10982883090068975788799657376065E-01; weight[110-1] = 0.10436130863141005225673171997668E-01; weight[111-1] = 0.98830429087554914716648010899606E-02; weight[112-1] = 0.93239550065309714787536985834029E-02; weight[113-1] = 0.87592065795403145773316804234385E-02; weight[114-1] = 0.81891404887415730817235884718726E-02; weight[115-1] = 0.76141028256526859356393930849227E-02; weight[116-1] = 0.70344427036681608755685893032552E-02; weight[117-1] = 0.64505120486899171845442463868748E-02; weight[118-1] = 0.58626653903523901033648343751367E-02; weight[119-1] = 0.52712596565634400891303815906251E-02; weight[120-1] = 0.46766539777779034772638165662478E-02; weight[121-1] = 0.40792095178254605327114733456293E-02; weight[122-1] = 0.34792893810051465908910894094105E-02; weight[123-1] = 0.28772587656289004082883197417581E-02; weight[124-1] = 0.22734860707492547802810838362671E-02; weight[125-1] = 0.16683488125171936761028811985672E-02; weight[126-1] = 0.10622766869538486959954760554099E-02; weight[127-1] = 0.45645726109586654495731936146574E-03; } else { cout << "\n"; cout << "GL_WEIGHTS - Fatal error!\n"; cout << " Illegal value of ORDER = " << order << "\n"; cout << " Legal values are 1, 3, 7, 15, 31, 63 and 127.\n"; exit ( 1 ); } return weight; } //****************************************************************************80 double gp_abscissa ( int level, int index ) //****************************************************************************80 // // Purpose: // // GP_ABSCISSA returns the I-th abscissa for a Gauss-Patterson rule. // // Discussion: // // The rule is specified by its level. // // The number of points in the rule, known as the order, is // related to the level by the formula: // // ORDER = 2^(LEVEL+1)-1. // // Only rules of order 1, 3, 7, 15, 31, 63 and 127 are allowed. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 December 2009 // // Author: // // John Burkardt // // Reference: // // Prem Kythe, Michael Schaeferkotter, // Handbook of Computational Methods for Integration, // Chapman and Hall, 2004, // ISBN: 1-58488-428-2, // LC: QA299.3.K98. // // Thomas Patterson, // The Optimal Addition of Points to Quadrature Formulae, // Mathematics of Computation, // Volume 22, Number 104, October 1968, pages 847-856. // // Parameters: // // Input, int LEVEL, the level of the rule. // 0 <= LEVEL <= 6. // // Input, int INDEX, the index of the point in the rule. // // Output, double GP_ABSCISSA, the value of the INDEX-th // abscissa in the rule of level LEVEL. // { int order; static double x_001[1] = { 0.0 }; static double x_003[3] = { -0.77459666924148337704, 0.0, 0.77459666924148337704 }; static double x_007[7] = { -0.96049126870802028342, -0.77459666924148337704, -0.43424374934680255800, 0.0, 0.43424374934680255800, 0.77459666924148337704, 0.96049126870802028342 }; static double x_015[15] = { -0.99383196321275502221, -0.96049126870802028342, -0.88845923287225699889, -0.77459666924148337704, -0.62110294673722640294, -0.43424374934680255800, -0.22338668642896688163, 0.0, 0.22338668642896688163, 0.43424374934680255800, 0.62110294673722640294, 0.77459666924148337704, 0.88845923287225699889, 0.96049126870802028342, 0.99383196321275502221 }; static double x_031[31] = { -0.99909812496766759766, -0.99383196321275502221, -0.98153114955374010687, -0.96049126870802028342, -0.92965485742974005667, -0.88845923287225699889, -0.83672593816886873550, -0.77459666924148337704, -0.70249620649152707861, -0.62110294673722640294, -0.53131974364437562397, -0.43424374934680255800, -0.33113539325797683309, -0.22338668642896688163, -0.11248894313318662575, 0.0, 0.11248894313318662575, 0.22338668642896688163, 0.33113539325797683309, 0.43424374934680255800, 0.53131974364437562397, 0.62110294673722640294, 0.70249620649152707861, 0.77459666924148337704, 0.83672593816886873550, 0.88845923287225699889, 0.92965485742974005667, 0.96049126870802028342, 0.98153114955374010687, 0.99383196321275502221, 0.99909812496766759766 }; static double x_063[63] = { -0.99987288812035761194, -0.99909812496766759766, -0.99720625937222195908, -0.99383196321275502221, -0.98868475754742947994, -0.98153114955374010687, -0.97218287474858179658, -0.96049126870802028342, -0.94634285837340290515, -0.92965485742974005667, -0.91037115695700429250, -0.88845923287225699889, -0.86390793819369047715, -0.83672593816886873550, -0.80694053195021761186, -0.77459666924148337704, -0.73975604435269475868, -0.70249620649152707861, -0.66290966002478059546, -0.62110294673722640294, -0.57719571005204581484, -0.53131974364437562397, -0.48361802694584102756, -0.43424374934680255800, -0.38335932419873034692, -0.33113539325797683309, -0.27774982202182431507, -0.22338668642896688163, -0.16823525155220746498, -0.11248894313318662575, -0.056344313046592789972, 0.0, 0.056344313046592789972, 0.11248894313318662575, 0.16823525155220746498, 0.22338668642896688163, 0.27774982202182431507, 0.33113539325797683309, 0.38335932419873034692, 0.43424374934680255800, 0.48361802694584102756, 0.53131974364437562397, 0.57719571005204581484, 0.62110294673722640294, 0.66290966002478059546, 0.70249620649152707861, 0.73975604435269475868, 0.77459666924148337704, 0.80694053195021761186, 0.83672593816886873550, 0.86390793819369047715, 0.88845923287225699889, 0.91037115695700429250, 0.92965485742974005667, 0.94634285837340290515, 0.96049126870802028342, 0.97218287474858179658, 0.98153114955374010687, 0.98868475754742947994, 0.99383196321275502221, 0.99720625937222195908, 0.99909812496766759766, 0.99987288812035761194 }; static double x_127[127] = { -0.99998243035489159858, -0.99987288812035761194, -0.99959879967191068325, -0.99909812496766759766, -0.99831663531840739253, -0.99720625937222195908, -0.99572410469840718851, -0.99383196321275502221, -0.99149572117810613240, -0.98868475754742947994, -0.98537149959852037111, -0.98153114955374010687, -0.97714151463970571416, -0.97218287474858179658, -0.96663785155841656709, -0.96049126870802028342, -0.95373000642576113641, -0.94634285837340290515, -0.93832039777959288365, -0.92965485742974005667, -0.92034002547001242073, -0.91037115695700429250, -0.89974489977694003664, -0.88845923287225699889, -0.87651341448470526974, -0.86390793819369047715, -0.85064449476835027976, -0.83672593816886873550, -0.82215625436498040737, -0.80694053195021761186, -0.79108493379984836143, -0.77459666924148337704, -0.75748396638051363793, -0.73975604435269475868, -0.72142308537009891548, -0.70249620649152707861, -0.68298743109107922809, -0.66290966002478059546, -0.64227664250975951377, -0.62110294673722640294, -0.59940393024224289297, -0.57719571005204581484, -0.55449513263193254887, -0.53131974364437562397, -0.50768775753371660215, -0.48361802694584102756, -0.45913001198983233287, -0.43424374934680255800, -0.40897982122988867241, -0.38335932419873034692, -0.35740383783153215238, -0.33113539325797683309, -0.30457644155671404334, -0.27774982202182431507, -0.25067873030348317661, -0.22338668642896688163, -0.19589750271110015392, -0.16823525155220746498, -0.14042423315256017459, -0.11248894313318662575, -0.084454040083710883710, -0.056344313046592789972, -0.028184648949745694339, 0.0, 0.028184648949745694339, 0.056344313046592789972, 0.084454040083710883710, 0.11248894313318662575, 0.14042423315256017459, 0.16823525155220746498, 0.19589750271110015392, 0.22338668642896688163, 0.25067873030348317661, 0.27774982202182431507, 0.30457644155671404334, 0.33113539325797683309, 0.35740383783153215238, 0.38335932419873034692, 0.40897982122988867241, 0.43424374934680255800, 0.45913001198983233287, 0.48361802694584102756, 0.50768775753371660215, 0.53131974364437562397, 0.55449513263193254887, 0.57719571005204581484, 0.59940393024224289297, 0.62110294673722640294, 0.64227664250975951377, 0.66290966002478059546, 0.68298743109107922809, 0.70249620649152707861, 0.72142308537009891548, 0.73975604435269475868, 0.75748396638051363793, 0.77459666924148337704, 0.79108493379984836143, 0.80694053195021761186, 0.82215625436498040737, 0.83672593816886873550, 0.85064449476835027976, 0.86390793819369047715, 0.87651341448470526974, 0.88845923287225699889, 0.89974489977694003664, 0.91037115695700429250, 0.92034002547001242073, 0.92965485742974005667, 0.93832039777959288365, 0.94634285837340290515, 0.95373000642576113641, 0.96049126870802028342, 0.96663785155841656709, 0.97218287474858179658, 0.97714151463970571416, 0.98153114955374010687, 0.98537149959852037111, 0.98868475754742947994, 0.99149572117810613240, 0.99383196321275502221, 0.99572410469840718851, 0.99720625937222195908, 0.99831663531840739253, 0.99909812496766759766, 0.99959879967191068325, 0.99987288812035761194, 0.99998243035489159858 }; static double x_255[255] = { -0.99999759637974846462, -0.99998243035489159858, -0.99994399620705437576, -0.99987288812035761194, -0.99976049092443204733, -0.99959879967191068325, -0.99938033802502358193, -0.99909812496766759766, -0.99874561446809511470, -0.99831663531840739253, -0.99780535449595727456, -0.99720625937222195908, -0.99651414591489027385, -0.99572410469840718851, -0.99483150280062100052, -0.99383196321275502221, -0.99272134428278861533, -0.99149572117810613240, -0.99015137040077015918, -0.98868475754742947994, -0.98709252795403406719, -0.98537149959852037111, -0.98351865757863272876, -0.98153114955374010687, -0.97940628167086268381, -0.97714151463970571416, -0.97473445975240266776, -0.97218287474858179658, -0.96948465950245923177, -0.96663785155841656709, -0.96364062156981213252, -0.96049126870802028342, -0.95718821610986096274, -0.95373000642576113641, -0.95011529752129487656, -0.94634285837340290515, -0.94241156519108305981, -0.93832039777959288365, -0.93406843615772578800, -0.92965485742974005667, -0.92507893290707565236, -0.92034002547001242073, -0.91543758715576504064, -0.91037115695700429250, -0.90514035881326159519, -0.89974489977694003664, -0.89418456833555902286, -0.88845923287225699889, -0.88256884024734190684, -0.87651341448470526974, -0.87029305554811390585, -0.86390793819369047715, -0.85735831088623215653, -0.85064449476835027976, -0.84376688267270860104, -0.83672593816886873550, -0.82952219463740140018, -0.82215625436498040737, -0.81462878765513741344, -0.80694053195021761186, -0.79909229096084140180, -0.79108493379984836143, -0.78291939411828301639, -0.77459666924148337704, -0.76611781930376009072, -0.75748396638051363793, -0.74869629361693660282, -0.73975604435269475868, -0.73066452124218126133, -0.72142308537009891548, -0.71203315536225203459, -0.70249620649152707861, -0.69281376977911470289, -0.68298743109107922809, -0.67301883023041847920, -0.66290966002478059546, -0.65266166541001749610, -0.64227664250975951377, -0.63175643771119423041, -0.62110294673722640294, -0.61031811371518640016, -0.59940393024224289297, -0.58836243444766254143, -0.57719571005204581484, -0.56590588542365442262, -0.55449513263193254887, -0.54296566649831149049, -0.53131974364437562397, -0.51955966153745702199, -0.50768775753371660215, -0.49570640791876146017, -0.48361802694584102756, -0.47142506587165887693, -0.45913001198983233287, -0.44673538766202847374, -0.43424374934680255800, -0.42165768662616330006, -0.40897982122988867241, -0.39621280605761593918, -0.38335932419873034692, -0.37042208795007823014, -0.35740383783153215238, -0.34430734159943802278, -0.33113539325797683309, -0.31789081206847668318, -0.30457644155671404334, -0.29119514851824668196, -0.27774982202182431507, -0.26424337241092676194, -0.25067873030348317661, -0.23705884558982972721, -0.22338668642896688163, -0.20966523824318119477, -0.19589750271110015392, -0.18208649675925219825, -0.16823525155220746498, -0.15434681148137810869, -0.14042423315256017459, -0.12647058437230196685, -0.11248894313318662575, -0.098482396598119202090, -0.084454040083710883710, -0.070406976042855179063, -0.056344313046592789972, -0.042269164765363603212, -0.028184648949745694339, -0.014093886410782462614, 0.0, 0.014093886410782462614, 0.028184648949745694339, 0.042269164765363603212, 0.056344313046592789972, 0.070406976042855179063, 0.084454040083710883710, 0.098482396598119202090, 0.11248894313318662575, 0.12647058437230196685, 0.14042423315256017459, 0.15434681148137810869, 0.16823525155220746498, 0.18208649675925219825, 0.19589750271110015392, 0.20966523824318119477, 0.22338668642896688163, 0.23705884558982972721, 0.25067873030348317661, 0.26424337241092676194, 0.27774982202182431507, 0.29119514851824668196, 0.30457644155671404334, 0.31789081206847668318, 0.33113539325797683309, 0.34430734159943802278, 0.35740383783153215238, 0.37042208795007823014, 0.38335932419873034692, 0.39621280605761593918, 0.40897982122988867241, 0.42165768662616330006, 0.43424374934680255800, 0.44673538766202847374, 0.45913001198983233287, 0.47142506587165887693, 0.48361802694584102756, 0.49570640791876146017, 0.50768775753371660215, 0.51955966153745702199, 0.53131974364437562397, 0.54296566649831149049, 0.55449513263193254887, 0.56590588542365442262, 0.57719571005204581484, 0.58836243444766254143, 0.59940393024224289297, 0.61031811371518640016, 0.62110294673722640294, 0.63175643771119423041, 0.64227664250975951377, 0.65266166541001749610, 0.66290966002478059546, 0.67301883023041847920, 0.68298743109107922809, 0.69281376977911470289, 0.70249620649152707861, 0.71203315536225203459, 0.72142308537009891548, 0.73066452124218126133, 0.73975604435269475868, 0.74869629361693660282, 0.75748396638051363793, 0.76611781930376009072, 0.77459666924148337704, 0.78291939411828301639, 0.79108493379984836143, 0.79909229096084140180, 0.80694053195021761186, 0.81462878765513741344, 0.82215625436498040737, 0.82952219463740140018, 0.83672593816886873550, 0.84376688267270860104, 0.85064449476835027976, 0.85735831088623215653, 0.86390793819369047715, 0.87029305554811390585, 0.87651341448470526974, 0.88256884024734190684, 0.88845923287225699889, 0.89418456833555902286, 0.89974489977694003664, 0.90514035881326159519, 0.91037115695700429250, 0.91543758715576504064, 0.92034002547001242073, 0.92507893290707565236, 0.92965485742974005667, 0.93406843615772578800, 0.93832039777959288365, 0.94241156519108305981, 0.94634285837340290515, 0.95011529752129487656, 0.95373000642576113641, 0.95718821610986096274, 0.96049126870802028342, 0.96364062156981213252, 0.96663785155841656709, 0.96948465950245923177, 0.97218287474858179658, 0.97473445975240266776, 0.97714151463970571416, 0.97940628167086268381, 0.98153114955374010687, 0.98351865757863272876, 0.98537149959852037111, 0.98709252795403406719, 0.98868475754742947994, 0.99015137040077015918, 0.99149572117810613240, 0.99272134428278861533, 0.99383196321275502221, 0.99483150280062100052, 0.99572410469840718851, 0.99651414591489027385, 0.99720625937222195908, 0.99780535449595727456, 0.99831663531840739253, 0.99874561446809511470, 0.99909812496766759766, 0.99938033802502358193, 0.99959879967191068325, 0.99976049092443204733, 0.99987288812035761194, 0.99994399620705437576, 0.99998243035489159858, 0.99999759637974846462 }; double value; order = i4_power ( 2, level + 1 ) - 1; if ( order < 1 ) { value = - r8_huge ( ); } else if ( index < 1 || order < index ) { value = - r8_huge ( ); } else if ( order == 1 ) { value = x_001[index-1]; } else if ( order == 3 ) { value = x_003[index-1]; } else if ( order == 7 ) { value = x_007[index-1]; } else if ( order == 15 ) { value = x_015[index-1]; } else if ( order == 31 ) { value = x_031[index-1]; } else if ( order == 63 ) { value = x_063[index-1]; } else if ( order == 127 ) { value = x_127[index-1]; } else if ( order == 255 ) { value = x_255[index-1]; } else { value = - r8_huge ( ); } return value; } //****************************************************************************80 double *gp_weights ( int order ) //****************************************************************************80 // // Purpose: // // GP_WEIGHTS sets weights for a Gauss-Patterson rule. // // Discussion: // // The zeroth rule, of order 1, is the standard Gauss-Legendre rule. // // The first rule, of order 3, is the standard Gauss-Legendre rule. // // The second rule, of order 7, includes the abscissas of the previous // rule. // // Each subsequent rule is nested in a similar way. Rules are available // of orders 1, 3, 7, 15, 31, 63, 127 and 255 // // Modified: // // 23 December 2009 // // Author: // // John Burkardt // // Reference: // // Prem Kythe, Michael Schaeferkotter, // Handbook of Computational Methods for Integration, // Chapman and Hall, 2004, // ISBN: 1-58488-428-2, // LC: QA299.3.K98. // // Thomas Patterson, // The Optimal Addition of Points to Quadrature Formulae, // Mathematics of Computation, // Volume 22, Number 104, October 1968, pages 847-856. // // Parameters: // // Input, int ORDER, the order of the rule. // ORDER must be 1, 3, 7, 15, 31, 63, 127 or 255. // // Output, double W[ORDER], the weights of the rule. // The weights are positive, symmetric and should sum to 2. // { double *w; static double w_001[1] = { 2.0 }; static double w_003[3] = { 0.555555555555555555556, 0.888888888888888888889, 0.555555555555555555556 }; static double w_007[7] = { 0.104656226026467265194, 0.268488089868333440729, 0.401397414775962222905, 0.450916538658474142345, 0.401397414775962222905, 0.268488089868333440729, 0.104656226026467265194 }; static double w_015[15] = { 0.0170017196299402603390, 0.0516032829970797396969, 0.0929271953151245376859, 0.134415255243784220360, 0.171511909136391380787, 0.200628529376989021034, 0.219156858401587496404, 0.225510499798206687386, 0.219156858401587496404, 0.200628529376989021034, 0.171511909136391380787, 0.134415255243784220360, 0.0929271953151245376859, 0.0516032829970797396969, 0.0170017196299402603390 }; static double w_031[31] = { 0.00254478079156187441540, 0.00843456573932110624631, 0.0164460498543878109338, 0.0258075980961766535646, 0.0359571033071293220968, 0.0464628932617579865414, 0.0569795094941233574122, 0.0672077542959907035404, 0.0768796204990035310427, 0.0857559200499903511542, 0.0936271099812644736167, 0.100314278611795578771, 0.105669893580234809744, 0.109578421055924638237, 0.111956873020953456880, 0.112755256720768691607, 0.111956873020953456880, 0.109578421055924638237, 0.105669893580234809744, 0.100314278611795578771, 0.0936271099812644736167, 0.0857559200499903511542, 0.0768796204990035310427, 0.0672077542959907035404, 0.0569795094941233574122, 0.0464628932617579865414, 0.0359571033071293220968, 0.0258075980961766535646, 0.0164460498543878109338, 0.00843456573932110624631, 0.00254478079156187441540 }; static double w_063[63] = { 0.000363221481845530659694, 0.00126515655623006801137, 0.00257904979468568827243, 0.00421763044155885483908, 0.00611550682211724633968, 0.00822300795723592966926, 0.0104982469096213218983, 0.0129038001003512656260, 0.0154067504665594978021, 0.0179785515681282703329, 0.0205942339159127111492, 0.0232314466399102694433, 0.0258696793272147469108, 0.0284897547458335486125, 0.0310735511116879648799, 0.0336038771482077305417, 0.0360644327807825726401, 0.0384398102494555320386, 0.0407155101169443189339, 0.0428779600250077344929, 0.0449145316536321974143, 0.0468135549906280124026, 0.0485643304066731987159, 0.0501571393058995374137, 0.0515832539520484587768, 0.0528349467901165198621, 0.0539054993352660639269, 0.0547892105279628650322, 0.0554814043565593639878, 0.0559784365104763194076, 0.0562776998312543012726, 0.0563776283603847173877, 0.0562776998312543012726, 0.0559784365104763194076, 0.0554814043565593639878, 0.0547892105279628650322, 0.0539054993352660639269, 0.0528349467901165198621, 0.0515832539520484587768, 0.0501571393058995374137, 0.0485643304066731987159, 0.0468135549906280124026, 0.0449145316536321974143, 0.0428779600250077344929, 0.0407155101169443189339, 0.0384398102494555320386, 0.0360644327807825726401, 0.0336038771482077305417, 0.0310735511116879648799, 0.0284897547458335486125, 0.0258696793272147469108, 0.0232314466399102694433, 0.0205942339159127111492, 0.0179785515681282703329, 0.0154067504665594978021, 0.0129038001003512656260, 0.0104982469096213218983, 0.00822300795723592966926, 0.00611550682211724633968, 0.00421763044155885483908, 0.00257904979468568827243, 0.00126515655623006801137, 0.000363221481845530659694 }; static double w_127[127] = { 0.0000505360952078625176247, 0.000180739564445388357820, 0.000377746646326984660274, 0.000632607319362633544219, 0.000938369848542381500794, 0.00128952408261041739210, 0.00168114286542146990631, 0.00210881524572663287933, 0.00256876494379402037313, 0.00305775341017553113613, 0.00357289278351729964938, 0.00411150397865469304717, 0.00467105037211432174741, 0.00524912345480885912513, 0.00584344987583563950756, 0.00645190005017573692280, 0.00707248999543355546805, 0.00770337523327974184817, 0.00834283875396815770558, 0.00898927578406413572328, 0.00964117772970253669530, 0.0102971169579563555237, 0.0109557333878379016480, 0.0116157233199551347270, 0.0122758305600827700870, 0.0129348396636073734547, 0.0135915710097655467896, 0.0142448773729167743063, 0.0148936416648151820348, 0.0155367755558439824399, 0.0161732187295777199419, 0.0168019385741038652709, 0.0174219301594641737472, 0.0180322163903912863201, 0.0186318482561387901863, 0.0192199051247277660193, 0.0197954950480974994880, 0.0203577550584721594669, 0.0209058514458120238522, 0.0214389800125038672465, 0.0219563663053178249393, 0.0224572658268160987071, 0.0229409642293877487608, 0.0234067774953140062013, 0.0238540521060385400804, 0.0242821652033365993580, 0.0246905247444876769091, 0.0250785696529497687068, 0.0254457699654647658126, 0.0257916269760242293884, 0.0261156733767060976805, 0.0264174733950582599310, 0.0266966229274503599062, 0.0269527496676330319634, 0.0271855132296247918192, 0.0273946052639814325161, 0.0275797495664818730349, 0.0277407021782796819939, 0.0278772514766137016085, 0.0279892182552381597038, 0.0280764557938172466068, 0.0281388499156271506363, 0.0281763190330166021307, 0.0281888141801923586938, 0.0281763190330166021307, 0.0281388499156271506363, 0.0280764557938172466068, 0.0279892182552381597038, 0.0278772514766137016085, 0.0277407021782796819939, 0.0275797495664818730349, 0.0273946052639814325161, 0.0271855132296247918192, 0.0269527496676330319634, 0.0266966229274503599062, 0.0264174733950582599310, 0.0261156733767060976805, 0.0257916269760242293884, 0.0254457699654647658126, 0.0250785696529497687068, 0.0246905247444876769091, 0.0242821652033365993580, 0.0238540521060385400804, 0.0234067774953140062013, 0.0229409642293877487608, 0.0224572658268160987071, 0.0219563663053178249393, 0.0214389800125038672465, 0.0209058514458120238522, 0.0203577550584721594669, 0.0197954950480974994880, 0.0192199051247277660193, 0.0186318482561387901863, 0.0180322163903912863201, 0.0174219301594641737472, 0.0168019385741038652709, 0.0161732187295777199419, 0.0155367755558439824399, 0.0148936416648151820348, 0.0142448773729167743063, 0.0135915710097655467896, 0.0129348396636073734547, 0.0122758305600827700870, 0.0116157233199551347270, 0.0109557333878379016480, 0.0102971169579563555237, 0.00964117772970253669530, 0.00898927578406413572328, 0.00834283875396815770558, 0.00770337523327974184817, 0.00707248999543355546805, 0.00645190005017573692280, 0.00584344987583563950756, 0.00524912345480885912513, 0.00467105037211432174741, 0.00411150397865469304717, 0.00357289278351729964938, 0.00305775341017553113613, 0.00256876494379402037313, 0.00210881524572663287933, 0.00168114286542146990631, 0.00128952408261041739210, 0.000938369848542381500794, 0.000632607319362633544219, 0.000377746646326984660274, 0.000180739564445388357820, 0.0000505360952078625176247 }; static double w_255[255] = { 0.69379364324108267170E-05, 0.25157870384280661489E-04, 0.53275293669780613125E-04, 0.90372734658751149261E-04, 0.13575491094922871973E-03, 0.18887326450650491366E-03, 0.24921240048299729402E-03, 0.31630366082226447689E-03, 0.38974528447328229322E-03, 0.46918492424785040975E-03, 0.55429531493037471492E-03, 0.64476204130572477933E-03, 0.74028280424450333046E-03, 0.84057143271072246365E-03, 0.94536151685852538246E-03, 0.10544076228633167722E-02, 0.11674841174299594077E-02, 0.12843824718970101768E-02, 0.14049079956551446427E-02, 0.15288767050877655684E-02, 0.16561127281544526052E-02, 0.17864463917586498247E-02, 0.19197129710138724125E-02, 0.20557519893273465236E-02, 0.21944069253638388388E-02, 0.23355251860571608737E-02, 0.24789582266575679307E-02, 0.26245617274044295626E-02, 0.27721957645934509940E-02, 0.29217249379178197538E-02, 0.30730184347025783234E-02, 0.32259500250878684614E-02, 0.33803979910869203823E-02, 0.35362449977167777340E-02, 0.36933779170256508183E-02, 0.38516876166398709241E-02, 0.40110687240750233989E-02, 0.41714193769840788528E-02, 0.43326409680929828545E-02, 0.44946378920320678616E-02, 0.46573172997568547773E-02, 0.48205888648512683476E-02, 0.49843645647655386012E-02, 0.51485584789781777618E-02, 0.53130866051870565663E-02, 0.54778666939189508240E-02, 0.56428181013844441585E-02, 0.58078616599775673635E-02, 0.59729195655081658049E-02, 0.61379152800413850435E-02, 0.63027734490857587172E-02, 0.64674198318036867274E-02, 0.66317812429018878941E-02, 0.67957855048827733948E-02, 0.69593614093904229394E-02, 0.71224386864583871532E-02, 0.72849479805538070639E-02, 0.74468208324075910174E-02, 0.76079896657190565832E-02, 0.77683877779219912200E-02, 0.79279493342948491103E-02, 0.80866093647888599710E-02, 0.82443037630328680306E-02, 0.84009692870519326354E-02, 0.85565435613076896192E-02, 0.87109650797320868736E-02, 0.88641732094824942641E-02, 0.90161081951956431600E-02, 0.91667111635607884067E-02, 0.93159241280693950932E-02, 0.94636899938300652943E-02, 0.96099525623638830097E-02, 0.97546565363174114611E-02, 0.98977475240487497440E-02, 0.10039172044056840798E-01, 0.10178877529236079733E-01, 0.10316812330947621682E-01, 0.10452925722906011926E-01, 0.10587167904885197931E-01, 0.10719490006251933623E-01, 0.10849844089337314099E-01, 0.10978183152658912470E-01, 0.11104461134006926537E-01, 0.11228632913408049354E-01, 0.11350654315980596602E-01, 0.11470482114693874380E-01, 0.11588074033043952568E-01, 0.11703388747657003101E-01, 0.11816385890830235763E-01, 0.11927026053019270040E-01, 0.12035270785279562630E-01, 0.12141082601668299679E-01, 0.12244424981611985899E-01, 0.12345262372243838455E-01, 0.12443560190714035263E-01, 0.12539284826474884353E-01, 0.12632403643542078765E-01, 0.12722884982732382906E-01, 0.12810698163877361967E-01, 0.12895813488012114694E-01, 0.12978202239537399286E-01, 0.13057836688353048840E-01, 0.13134690091960152836E-01, 0.13208736697529129966E-01, 0.13279951743930530650E-01, 0.13348311463725179953E-01, 0.13413793085110098513E-01, 0.13476374833816515982E-01, 0.13536035934956213614E-01, 0.13592756614812395910E-01, 0.13646518102571291428E-01, 0.13697302631990716258E-01, 0.13745093443001896632E-01, 0.13789874783240936517E-01, 0.13831631909506428676E-01, 0.13870351089139840997E-01, 0.13906019601325461264E-01, 0.13938625738306850804E-01, 0.13968158806516938516E-01, 0.13994609127619079852E-01, 0.14017968039456608810E-01, 0.14038227896908623303E-01, 0.14055382072649964277E-01, 0.14069424957813575318E-01, 0.14080351962553661325E-01, 0.14088159516508301065E-01, 0.14092845069160408355E-01, 0.14094407090096179347E-01, 0.14092845069160408355E-01, 0.14088159516508301065E-01, 0.14080351962553661325E-01, 0.14069424957813575318E-01, 0.14055382072649964277E-01, 0.14038227896908623303E-01, 0.14017968039456608810E-01, 0.13994609127619079852E-01, 0.13968158806516938516E-01, 0.13938625738306850804E-01, 0.13906019601325461264E-01, 0.13870351089139840997E-01, 0.13831631909506428676E-01, 0.13789874783240936517E-01, 0.13745093443001896632E-01, 0.13697302631990716258E-01, 0.13646518102571291428E-01, 0.13592756614812395910E-01, 0.13536035934956213614E-01, 0.13476374833816515982E-01, 0.13413793085110098513E-01, 0.13348311463725179953E-01, 0.13279951743930530650E-01, 0.13208736697529129966E-01, 0.13134690091960152836E-01, 0.13057836688353048840E-01, 0.12978202239537399286E-01, 0.12895813488012114694E-01, 0.12810698163877361967E-01, 0.12722884982732382906E-01, 0.12632403643542078765E-01, 0.12539284826474884353E-01, 0.12443560190714035263E-01, 0.12345262372243838455E-01, 0.12244424981611985899E-01, 0.12141082601668299679E-01, 0.12035270785279562630E-01, 0.11927026053019270040E-01, 0.11816385890830235763E-01, 0.11703388747657003101E-01, 0.11588074033043952568E-01, 0.11470482114693874380E-01, 0.11350654315980596602E-01, 0.11228632913408049354E-01, 0.11104461134006926537E-01, 0.10978183152658912470E-01, 0.10849844089337314099E-01, 0.10719490006251933623E-01, 0.10587167904885197931E-01, 0.10452925722906011926E-01, 0.10316812330947621682E-01, 0.10178877529236079733E-01, 0.10039172044056840798E-01, 0.98977475240487497440E-02, 0.97546565363174114611E-02, 0.96099525623638830097E-02, 0.94636899938300652943E-02, 0.93159241280693950932E-02, 0.91667111635607884067E-02, 0.90161081951956431600E-02, 0.88641732094824942641E-02, 0.87109650797320868736E-02, 0.85565435613076896192E-02, 0.84009692870519326354E-02, 0.82443037630328680306E-02, 0.80866093647888599710E-02, 0.79279493342948491103E-02, 0.77683877779219912200E-02, 0.76079896657190565832E-02, 0.74468208324075910174E-02, 0.72849479805538070639E-02, 0.71224386864583871532E-02, 0.69593614093904229394E-02, 0.67957855048827733948E-02, 0.66317812429018878941E-02, 0.64674198318036867274E-02, 0.63027734490857587172E-02, 0.61379152800413850435E-02, 0.59729195655081658049E-02, 0.58078616599775673635E-02, 0.56428181013844441585E-02, 0.54778666939189508240E-02, 0.53130866051870565663E-02, 0.51485584789781777618E-02, 0.49843645647655386012E-02, 0.48205888648512683476E-02, 0.46573172997568547773E-02, 0.44946378920320678616E-02, 0.43326409680929828545E-02, 0.41714193769840788528E-02, 0.40110687240750233989E-02, 0.38516876166398709241E-02, 0.36933779170256508183E-02, 0.35362449977167777340E-02, 0.33803979910869203823E-02, 0.32259500250878684614E-02, 0.30730184347025783234E-02, 0.29217249379178197538E-02, 0.27721957645934509940E-02, 0.26245617274044295626E-02, 0.24789582266575679307E-02, 0.23355251860571608737E-02, 0.21944069253638388388E-02, 0.20557519893273465236E-02, 0.19197129710138724125E-02, 0.17864463917586498247E-02, 0.16561127281544526052E-02, 0.15288767050877655684E-02, 0.14049079956551446427E-02, 0.12843824718970101768E-02, 0.11674841174299594077E-02, 0.10544076228633167722E-02, 0.94536151685852538246E-03, 0.84057143271072246365E-03, 0.74028280424450333046E-03, 0.64476204130572477933E-03, 0.55429531493037471492E-03, 0.46918492424785040975E-03, 0.38974528447328229322E-03, 0.31630366082226447689E-03, 0.24921240048299729402E-03, 0.18887326450650491366E-03, 0.13575491094922871973E-03, 0.90372734658751149261E-04, 0.53275293669780613125E-04, 0.25157870384280661489E-04, 0.69379364324108267170E-05 }; w = new double[order]; if ( order == 1 ) { r8vec_copy ( order, w_001, w ); } else if ( order == 3 ) { r8vec_copy ( order, w_003, w ); } else if ( order == 7 ) { r8vec_copy ( order, w_007, w ); } else if ( order == 15 ) { r8vec_copy ( order, w_015, w ); } else if ( order == 31 ) { r8vec_copy ( order, w_031, w ); } else if ( order == 63 ) { r8vec_copy ( order, w_063, w ); } else if ( order == 127 ) { r8vec_copy ( order, w_127, w ); } else if ( order == 255 ) { r8vec_copy ( order, w_255, w ); } else { std::cerr << "\n"; std::cerr << "GP_WEIGHTS - Fatal error!\n"; std::cerr << " Unexpected value of ORDER = " << order << ".\n"; std::exit ( 1 ); } return w; } //****************************************************************************80 int i4_log_2 ( int i ) //****************************************************************************80 // // Purpose: // // I4_LOG_2 returns the integer part of the logarithm base 2 of an I4. // // Example: // // I I4_LOG_10 // ----- -------- // 0 0 // 1 0 // 2 1 // 3 1 // 4 2 // 5 2 // 7 2 // 8 3 // 9 3 // 1000 9 // 1024 10 // // Discussion: // // I4_LOG_2 ( I ) + 1 is the number of binary digits in I. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 January 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int I, the number whose logarithm base 2 is desired. // // Output, int I4_LOG_2, the integer part of the logarithm base 2 of // the absolute value of X. // { int i_abs; int two_pow; int value; if ( i == 0 ) { value = 0; } else { value = 0; two_pow = 2; i_abs = abs ( i ); while ( two_pow <= i_abs ) { value = value + 1; two_pow = two_pow * 2; } } return value; } //****************************************************************************80 int i4_max ( int i1, int i2 ) //****************************************************************************80 // // Purpose: // // I4_MAX returns the maximum of two I4's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int I1, I2, are two integers to be compared. // // Output, int I4_MAX, the larger of I1 and I2. // { int value; if ( i2 < i1 ) { value = i1; } else { value = i2; } return value; } //****************************************************************************80 int i4_min ( int i1, int i2 ) //****************************************************************************80 // // Purpose: // // I4_MIN returns the minimum of two I4's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 October 1998 // // Author: // // John Burkardt // // Parameters: // // Input, int I1, I2, two integers to be compared. // // Output, int I4_MIN, the smaller of I1 and I2. // { int value; if ( i1 < i2 ) { value = i1; } else { value = i2; } return value; } //****************************************************************************80 int i4_modp ( int i, int j ) //****************************************************************************80 // // Purpose: // // I4_MODP returns the nonnegative remainder of I4 division. // // Discussion: // // If // NREM = I4_MODP ( I, J ) // NMULT = ( I - NREM ) / J // then // I = J * NMULT + NREM // where NREM is always nonnegative. // // The MOD function computes a result with the same sign as the // quantity being divided. Thus, suppose you had an angle A, // and you wanted to ensure that it was between 0 and 360. // Then mod(A,360) would do, if A was positive, but if A // was negative, your result would be between -360 and 0. // // On the other hand, I4_MODP(A,360) is between 0 and 360, always. // // I J MOD I4_MODP I4_MODP Factorization // // 107 50 7 7 107 = 2 * 50 + 7 // 107 -50 7 7 107 = -2 * -50 + 7 // -107 50 -7 43 -107 = -3 * 50 + 43 // -107 -50 -7 43 -107 = 3 * -50 + 43 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 May 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int I, the number to be divided. // // Input, int J, the number that divides I. // // Output, int I4_MODP, the nonnegative remainder when I is // divided by J. // { int value; if ( j == 0 ) { cout << "\n"; cout << "I4_MODP - Fatal error!\n"; cout << " I4_MODP ( I, J ) called with J = " << j << "\n"; exit ( 1 ); } value = i % j; if ( value < 0 ) { value = value + abs ( j ); } return value; } //****************************************************************************80 int i4_power ( int i, int j ) //****************************************************************************80 // // Purpose: // // I4_POWER returns the value of I^J. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 April 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int I, J, the base and the power. J should be nonnegative. // // Output, int I4_POWER, the value of I^J. // { int k; int value; if ( j < 0 ) { if ( i == 1 ) { value = 1; } else if ( i == 0 ) { cout << "\n"; cout << "I4_POWER - Fatal error!\n"; cout << " I^J requested, with I = 0 and J negative.\n"; exit ( 1 ); } else { value = 0; } } else if ( j == 0 ) { if ( i == 0 ) { cout << "\n"; cout << "I4_POWER - Fatal error!\n"; cout << " I^J requested, with I = 0 and J = 0.\n"; exit ( 1 ); } else { value = 1; } } else if ( j == 1 ) { value = i; } else { value = 1; for ( k = 1; k <= j; k++ ) { value = value * i; } } return value; } //****************************************************************************80 int i4vec_product ( int n, int a[] ) //****************************************************************************80 // // Purpose: // // I4VEC_PRODUCT multiplies the entries of an integer vector. // // Example: // // A = ( 1, 2, 3, 4 ) // // I4VEC_PRODUCT = 24 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 November 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vector. // // Input, int A[N], the vector // // Output, int I4VEC_PRODUCT, the product of the entries of A. // { int i; int product; product = 1; for ( i = 0; i < n; i++ ) { product = product * a[i]; } return product; } //****************************************************************************80 int *index_level_own ( int level, int level_max, int dim_num, int point_num, int grid_index[], int grid_base[] ) //****************************************************************************80 // // Purpose: // // INDEX_LEVEL_OWN: determine first level at which given index is generated. // // Discussion: // // We are constructing a sparse grid of OWN points. The grid // is built up of product grids, with a characteristic LEVEL. // // We are concerned with identifying points in this product grid which // have actually been generated previously, on a lower value of LEVEL. // // This routine determines the lowest value of LEVEL at which each of // the input points would be generated. // // In 1D, given LEVEL, the number of points is ORDER = 2**(LEVEL+1) + 1, // (except that LEVEL = 0 implies ORDER = 1), the BASE is (ORDER-1)/2, // and the point INDEX values range from -BASE to +BASE. // // The values of INDEX and BASE allow us to determine the abstract // properties of the point. In particular, if INDEX is 0, the corresponding // abscissa is 0, the special "nested" value we need to take care of. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 07 October 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, the level at which these points were // generated. LEVEL_MIN <= LEVEL <= LEVEL_MAX. // // Input, int LEVEL_MAX, the maximum level. // // Input, int DIM_NUM, the spatial dimension. // // Input, int POINT_NUM, the number of points to be tested. // // Input, int GRID_INDEX[DIM_NUM*POINT_NUM], the indices of the // points to be tested. // // Input, int GRID_BASE[DIM_NUM], the "base", which is essentially // the denominator of the index. // // Output, int INDEX_LEVEL_OWN[POINT_NUM], the value of LEVEL at // which the point would first be generated. This will be the same as // the input value of LEVEL, unless the point has an INDEX of 0 and // a corresponding BASE that is NOT zero. // { int dim; int *grid_level; int level_min; int point; grid_level = new int[point_num]; if ( dim_num == 1 ) { level_min = level_max; } else { level_min = 0; } // // If a point has a DIM-th component whose INDEX is 0, then the // value of LEVEL at which this point would first be generated is // less than LEVEL, unless the DIM-th component of GRID_BASE is 0. // for ( point = 0; point < point_num; point++ ) { grid_level[point] = i4_max ( level, level_min ); for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_index[dim+point*dim_num] == 0 ) { grid_level[point] = i4_max ( grid_level[point] - grid_base[dim], level_min ); } } } return grid_level; } //****************************************************************************80 int index_to_level_closed ( int dim_num, int t[], int order, int level_max ) //****************************************************************************80 // // Purpose: // // INDEX_TO_LEVEL_CLOSED determines the level of a point given its index. // // 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 T[DIM_NUM], the grid indices of a point in a 1D closed rule. // 0 <= T[I] <= ORDER. // // Input, int ORDER, the order of the rule. // // Input, int LEVEL_MAX, the level with respect to which the // index applies. // // Output, int INDEX_TO_LEVEL_CLOSED, the first level on which // the point associated with the given index will appear. // { int dim; int level; int s; int value; value = 0; for ( dim = 0; dim < dim_num; dim++ ) { s = t[dim]; s = i4_modp ( s, order ); if ( s == 0 ) { level = 0; } else { level = level_max; while ( ( s % 2 ) == 0 ) { s = s / 2; level = level - 1; } } if ( level == 0 ) { level = 1; } else if ( level == 1 ) { level = 0; } value = value + level; } return value; } //****************************************************************************80 int index_to_level_open ( int dim_num, int t[], int order, int level_max ) //****************************************************************************80 // // Purpose: // // INDEX_TO_LEVEL_OPEN determines the level of a point given its index. // // Modified: // // 19 April 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 T[DIM_NUM], the grid index of a point. // // Input, int ORDER, the order of the rule. // // Input, int LEVEL_MAX, the level with respect to which the // index applies. // // Output, int INDEX_TO_LEVEL_OPEN, the first level on which // the point associated with the given index will appear. // { int dim; int level; int s; int value; value = 0; for ( dim = 0; dim < dim_num; dim++ ) { s = t[dim]; s = i4_modp ( s, order ); if ( s == 0 ) { level = 0; } else { level = level_max; while ( ( s % 2 ) == 0 ) { s = s / 2; level = level - 1; } } if ( level == 0 ) { level = 1; } else if ( level == 1 ) { level = 0; } value = value + level; } return value; } //****************************************************************************80 void level_to_order_closed ( int dim_num, int level[], int order[] ) //****************************************************************************80 // // Purpose: // // LEVEL_TO_ORDER_CLOSED converts a level to an order for closed rules. // // Discussion: // // Sparse grids can naturally be nested. A natural scheme is to use // a series of one-dimensional rules arranged in a series of "levels" // whose order roughly doubles with each step. // // The arrangement described here works naturally for the Clenshaw Curtis // and Newton Cotes closed rules. // // The idea is that we start with LEVEL = 0, ORDER = 1 indicating the single // point at the center, and for all values afterwards, we use the // relationship // // ORDER = 2^LEVEL + 1 // // The following table shows how the growth will occur: // // Level Order // // 0 1 // 1 3 = 2 + 1 // 2 5 = 4 + 1 // 3 9 = 8 + 1 // 4 17 = 16 + 1 // 5 33 = 32 + 1 // // For the Clenshaw Curtis and Newton Cotes Closed rules, the point growth // is nested. If we have ORDER points on a particular LEVEL, the next // level includes all these old points, plus ORDER-1 new points, formed // in the gaps between successive pairs of old points. // // Level Order = New + Old // // 0 1 = 1 + 0 // 1 3 = 2 + 1 // 2 5 = 2 + 3 // 3 9 = 4 + 5 // 4 17 = 8 + 9 // 5 33 = 16 + 17 // // In this routine, we assume that a vector of levels is given, // and the corresponding orders are desired. // // 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[DIM_NUM], the nesting level. // // Output, int ORDER[DIM_NUM], the order (number of points) // of the rule. // { int dim; for ( dim = 0; dim < dim_num; dim++ ) { if ( level[dim] < 0 ) { order[dim] = -1; } else if ( level[dim] == 0 ) { order[dim] = 1; } else { order[dim] = i4_power ( 2, level[dim] ) + 1 ; } } return; } //****************************************************************************80 void level_to_order_open ( int dim_num, int level[], int order[] ) //****************************************************************************80 // // Purpose: // // LEVEL_TO_ORDER_OPEN converts a level to an order for open rules. // // Discussion: // // Sparse grids can naturally be nested. A natural scheme is to use // a series of one-dimensional rules arranged in a series of "levels" // whose order roughly doubles with each step. // // The arrangement described here works naturally for the Fejer Type 1, // Fejer Type 2, Newton Cotes Open, Newton Cotes Half Open, // and Gauss-Patterson rules. It also can be used, partially, to describe // the growth of Gauss-Legendre rules. // // The idea is that we start with LEVEL = 0, ORDER = 1 indicating the single // point at the center, and for all values afterwards, we use the relationship // // ORDER = 2**(LEVEL+1) - 1. // // The following table shows how the growth will occur: // // Level Order // // 0 1 // 1 3 = 4 - 1 // 2 7 = 8 - 1 // 3 15 = 16 - 1 // 4 31 = 32 - 1 // 5 63 = 64 - 1 // // For the Fejer Type 1, Fejer Type 2, Newton Cotes Open, // Newton Cotes Open Half, and Gauss-Patterson rules, the point growth is // nested. If we have ORDER points on a particular LEVEL, the next level // includes all these old points, plus ORDER+1 new points, formed in the // gaps between successive pairs of old points plus an extra point at each // end. // // Level Order = New + Old // // 0 1 = 1 + 0 // 1 3 = 2 + 1 // 2 7 = 4 + 3 // 3 15 = 8 + 7 // 4 31 = 16 + 15 // 5 63 = 32 + 31 // // If we use a series of Gauss-Legendre rules, then there is almost no // nesting, except that the central point is shared. If we insist on // producing a comparable series of such points, then the "nesting" behavior // is as follows: // // Level Order = New + Old // // 0 1 = 1 + 0 // 1 3 = 2 + 1 // 2 7 = 6 + 1 // 3 15 = 14 + 1 // 4 31 = 30 + 1 // 5 63 = 62 + 1 // // Moreover, if we consider ALL the points used in such a set of "nested" // Gauss-Legendre rules, then we must sum the "NEW" column, and we see that // we get roughly twice as many points as for the truly nested rules. // // In this routine, we assume that a vector of levels is given, // and the corresponding orders are desired. // // Modified: // // 19 April 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[DIM_NUM], the nesting level. // // Output, int ORDER[DIM_NUM], the order (number of points) // of the rule. // { int dim; for ( dim = 0; dim < dim_num; dim++ ) { if ( level[dim] < 0 ) { order[dim] = -1; } else if ( level[dim] == 0 ) { order[dim] = 1; } else { order[dim] = i4_power ( 2, level[dim] + 1 ) - 1 ; } } return; } //****************************************************************************80 void levels_index ( int dim_num, int level_max, int rule, int point_num, int grid_index[], int grid_base[] ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX indexes a sparse grid. // // Discussion: // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // The necessary dimensions of GRID_INDEX can be determined by // calling LEVELS_INDEX_SIZE first. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 March 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 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. // // 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 rules associated with each point and dimension. // { if ( rule == 1 ) { levels_index_cfn ( dim_num, level_max, point_num, grid_index, grid_base ); } else if ( 2 <= rule && rule <= 4 ) { levels_index_ofn ( dim_num, level_max, point_num, grid_index, grid_base ); } else if ( 5 <= rule && rule <= 6 ) { levels_index_own ( dim_num, level_max, point_num, grid_index, grid_base ); } else if ( 7 == rule ) { levels_index_onn ( dim_num, level_max, point_num, grid_index, grid_base ); } else { cout << "\n"; cout << "LEVELS_INDEX - Fatal error!\n"; cout << " Unrecognized rule number = " << rule << "\n"; exit ( 1 ); } return; } //****************************************************************************80 void levels_index_cfn ( int dim_num, int level_max, int point_num, int grid_index[], int grid_base[] ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_CFN indexes a sparse grid made from CFN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of CLOSED FULLY NESTED 1D quadrature rules. // // CFN rules include Clenshaw Curtis rules. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // The necessary dimensions of GRID_INDEX can be determined by // calling LEVELS_INDEX_SIZE_CFN first. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 LEVELS_INDEX_CFN[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 dim; int factor; int *grid_index2; int *grid_level; int h; int j; int level; int *level_1d; bool more; int *order_1d; int order_nd; int point; int point_num2; int t; // // The outer loop generates LEVELs from 0 to LEVEL_MAX. // point_num2 = 0; level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_closed ( dim_num, level_1d, order_1d ); // // The product of the 1D orders gives us the number of points in this grid. // order_nd = i4vec_product ( dim_num, order_1d ); // // The inner (hidden) loop generates all points corresponding to given grid. // grid_index2 = multigrid_index_cfn ( dim_num, order_1d, order_nd ); // // Adjust these grid indices to reflect LEVEL_MAX. // multigrid_scale_closed ( dim_num, order_nd, level_max, level_1d, grid_index2 ); // // Determine the first level of appearance of each of the points. // grid_level = abscissa_level_closed_nd ( level_max, dim_num, order_nd, grid_index2 ); // // Only keep those points which first appear on this level. // for ( point = 0; point < order_nd; point++ ) { if ( grid_level[point] == level ) { if ( point_num <= point_num2 ) { cout << "\n"; cout << "LEVELS_INDEX_CFN - Fatal error!\n"; cout << " Exceeding maximum point index POINT_NUM = " << point_num << "\n"; exit ( 1 ); } for ( dim = 0; dim < dim_num; dim++ ) { grid_base[dim+point_num2*dim_num] = order_1d[dim]; grid_index[dim+point_num2*dim_num] = grid_index2[dim+point*dim_num]; } point_num2 = point_num2 + 1; } } delete [] grid_index2; delete [] grid_level; if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; if ( point_num2 < point_num ) { cout << "\n"; cout << "LEVELS_INDEX_CFN - Fatal error!\n"; cout << " Set fewer points than POINT_NUM = " << point_num << "\n"; exit ( 1 ); } return; } //****************************************************************************80 void levels_index_ofn ( int dim_num, int level_max, int point_num, int grid_index[], int grid_base[] ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_OFN indexes a sparse grid made from OFN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN FULLY NESTED 1D quadrature rules. // // OFN rules include Fejer 1, Fejer 2, and Gauss Patterson rules. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // The necessary dimensions of GRID_INDEX can be determined by // calling LEVELS_INDEX_SIZE_OFN first. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 rules associated with each point and dimension. // { int dim; int factor; int *grid_index2; int h; int level; int *level_1d; bool more; int *order_1d; int order_nd; int point; int point_num2; int t; bool test; // // The outer loop generates LEVELs from 0 to LEVEL_MAX. // level_1d = new int[dim_num]; order_1d = new int[dim_num]; point_num2 = 0; for ( level = 0; level <= level_max; level++ ) { // // The middle loop generates the next partition that adds up to LEVEL. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_open ( dim_num, level_1d, order_1d ); // // The product of the 1D orders gives us the number of points in this grid. // order_nd = i4vec_product ( dim_num, order_1d ); // // The inner (hidden) loop generates all points corresponding to given grid. // grid_index2 = multigrid_index_ofn ( dim_num, order_1d, order_nd ); // // Only keep those points which first appear on this level. // If you keep a point, it is necessary to rescale each of its components // so that we save the coordinates as they apply on the final grid. // for ( point = 0; point < order_nd; point++ ) { test = true; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_index2[dim+point*dim_num] % 2 == 0 ) { test = false; } } if ( test ) { if ( point_num <= point_num2 ) { cout << "LEVELS_INDEX_OFN - Fatal error!\n"; cout << " Exceeding maximum point index POINT_NUM = " << point_num << "\n"; exit ( 1 ); } for ( dim = 0; dim < dim_num; dim++ ) { grid_base[dim+point_num2*dim_num] = order_1d[dim]; grid_index[dim+point_num2*dim_num] = i4_power ( 2, level_max - level_1d[dim] ) * grid_index2[dim+point*dim_num]; } point_num2 = point_num2 + 1; } } delete [] grid_index2; if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; if ( point_num2 < point_num ) { cout << "\n"; cout << "LEVELS_INDEX_OFN - Fatal error!\n"; cout << " Set fewer points than POINT_NUM = " << point_num << "\n"; exit ( 1 ); } return; } //****************************************************************************80 void levels_index_onn ( int dim_num, int level_max, int point_num, int grid_index [], int grid_base[] ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_ONN indexes a sparse grid made from ONN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN NON NESTED 1D quadrature rules. // // ONN rules include Gauss Laguerre. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // The necessary dimensions of GRID_INDEX can be determined by // calling LEVELS_INDEX_SIZE_ONN first. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 rules associated with each point and dimension. // { int dim; int factor; int *grid_base2; int *grid_index2; int h; int j; int level; int *level_1d; int level_min; bool more; int *order_1d; int order_nd; int point; int point_num2; int t; // // The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. // point_num2 = 0; level_min = i4_max ( 0, level_max + 1 - dim_num ); grid_base2 = new int[dim_num]; level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_open ( dim_num, level_1d, order_1d ); 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. // order_nd = i4vec_product ( dim_num, order_1d ); // // The inner (hidden) loop generates all points corresponding to given grid. // grid_index2 = multigrid_index_onn ( dim_num, order_1d, order_nd ); // // Only keep those points which first appear on this level. // for ( point = 0; point < order_nd; point++ ) { if ( point_num <= point_num2 ) { cout << "\n"; cout << "LEVELS_INDEX_ONN - Fatal error!\n"; cout << " Exceeding maximum point index POINT_NUM = " << point_num << "\n"; exit ( 1 ); } 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 = point_num2 + 1; } delete [] grid_index2; if ( !more ) { break; } } } delete [] grid_base2; delete [] level_1d; delete [] order_1d; if ( point_num2 < point_num ) { cout << "\n"; cout << "LEVELS_INDEX_ONN - Fatal error!\n"; cout << " Set fewer points than POINT_NUM = " << point_num << "\n"; exit ( 1 ); } return; } //****************************************************************************80 void levels_index_own ( int dim_num, int level_max, int point_num, int grid_index [], int grid_base[] ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_OWN indexes a sparse grid made from OWN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN WEAKLY NESTED 1D quadrature rules. // // OWN rules include Gauss Hermite and Gauss Legendre. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // The necessary dimensions of GRID_INDEX can be determined by // calling LEVELS_INDEX_SIZE_OWN first. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 rules associated with each point and dimension. // { int dim; int factor; int *grid_base2; int *grid_index2; int *grid_level; int h; int j; int level; int *level_1d; int level_min; bool more; int *order_1d; int order_nd; int point; int point_num2; int t; // // The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. // point_num2 = 0; if ( dim_num == 1 ) { level_min = level_max; } else { level_min = 0; } grid_base2 = new int[dim_num]; level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_open ( dim_num, level_1d, order_1d ); 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. // order_nd = i4vec_product ( dim_num, order_1d ); // // The inner (hidden) loop generates all points corresponding to given grid. // grid_index2 = multigrid_index_own ( 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. // grid_level = index_level_own ( 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++ ) { if ( grid_level[point] == level ) { if ( point_num <= point_num2 ) { cout << "\n"; cout << "LEVELS_INDEX_OWN - Fatal error!\n"; cout << " Exceeding maximum point index POINT_NUM = " << point_num << "\n"; exit ( 1 ); } 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 = point_num2 + 1; } } delete [] grid_index2; delete [] grid_level; if ( !more ) { break; } } } delete [] grid_base2; delete [] level_1d; delete [] order_1d; if ( point_num2 < point_num ) { cout << "\n"; cout << "LEVELS_INDEX_OWN - Fatal error!\n"; cout << " Set fewer points than POINT_NUM = " << point_num << "\n"; exit ( 1 ); } return; } //****************************************************************************80 int levels_index_size ( int dim_num, int level_max, int rule ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_SIZE sizes a sparse grid. // // Discussion: // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 December 2009 // // 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, integer ( kind = 4 ) DIM_NUM, the spatial dimension. // // Input, integer ( kind = 4 ) LEVEL_MAX, the maximum value of LEVEL. // // Input, integer ( kind = 4 ) 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, int LEVELS_INDEX_SIZE, the total number of unique // points in the grids. // { int point_num; if ( rule == 1 ) { point_num = sparse_grid_cc_size ( dim_num, level_max ); } else if ( 2 <= rule && rule <= 4 ) { point_num = sparse_grid_ofn_size ( dim_num, level_max ); } else if ( 5 <= rule && rule <= 6 ) { point_num = levels_index_size_own ( dim_num, level_max ); } else if ( 7 == rule ) { point_num = levels_index_size_onn ( dim_num, level_max ); } else { point_num = -1; cout << "\n"; cout << "LEVELS_INDEX_SIZE - Fatal error!\n"; cout << " Unrecognized value of RULE = " << rule << "\n"; exit ( 1 ); } return point_num; } //****************************************************************************80 int levels_index_size_cfn ( int dim_num, int level_max ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_SIZE_CFN sizes a sparse grid made from CFN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of CLOSED FULLY NESTED 1D quadrature rules. // // CFN rules include Clenshaw Curtis rules. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 LEVELS_INDEX_SIZE_CFN, the number of points in the grid. // { int dim; int factor; int *grid_index; int *grid_level; int h; int j; int level; int *level_1d; bool more; int *order_1d; int order_max; int order_nd; int point; int point_num; int t; // // Special case. // if ( level_max == 0 ) { point_num = 1; return point_num; } // // The outer loop generates LEVELs from 0 to LEVEL_MAX. // point_num = 0; level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_closed ( dim_num, level_1d, order_1d ); // // The product of the 1D orders gives us the number of points in this grid. // order_nd = i4vec_product ( dim_num, order_1d ); // // The inner (hidden) loop generates all points corresponding to given grid. // grid_index = multigrid_index_cfn ( dim_num, order_1d, order_nd ); // // Adjust these grid indices to reflect LEVEL_MAX. // multigrid_scale_closed ( dim_num, order_nd, level_max, level_1d, grid_index ); // // Determine the first level of appearance of each of the points. // grid_level = abscissa_level_closed_nd ( level_max, dim_num, order_nd, grid_index ); // // Only keep those points which first appear on this level. // for ( point = 0; point < order_nd; point++ ) { if ( grid_level[point] == level ) { point_num = point_num + 1; } } delete [] grid_index; delete [] grid_level; if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; return point_num; } //****************************************************************************80 int levels_index_size_onn ( int dim_num, int level_max ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_SIZE_ONN sizes a sparse grid made from ONN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN NON-NESTED 1D quadrature rules. // // ONN rules include Gauss Laguerre. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 LEVELS_INDEX_SIZE_ONN, the number of points in the grid. // { int dim; int h; int level; int *level_1d; int level_min; bool more; int num; int *order_1d; int order_nd; int point_num; int t; // // Special case. // if ( level_max == 0 ) { point_num = 1; return point_num; } // // The outer loop generates LEVELs from 0 to LEVEL_MAX. // point_num = 0; level_min = i4_max ( 0, level_max + 1 - dim_num ); level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_open ( dim_num, level_1d, order_1d ); point_num = point_num + i4vec_product ( dim_num, order_1d ); if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; return point_num; } //****************************************************************************80 int levels_index_size_own ( int dim_num, int level_max ) //****************************************************************************80 // // Purpose: // // LEVELS_INDEX_SIZE_OWN sizes a sparse grid made from OWN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN WEAKLY NESTED 1D quadrature rules. // // OWN rules include Gauss Hermite and Gauss Legendre. // // The sparse grid is the logical sum of product grids with total LEVEL // between LEVEL_MIN and LEVEL_MAX. // // Oddly enough, in order to count the number of points, we will // behave as though LEVEL_MIN was zero. This is because our computation // concentrates on throwing away all points generated at lower levels, // but, in fact, if we start at a nonzero level, we need to include // on that level all the points that would have been generated on lower // levels. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 LEVELS_INDEX_SIZE_OWN, the number of points in the grid. // { int dim; int h; int level; int *level_1d; int level_min; bool more; int num; int *order_1d; int order_nd; int point_num; int t; // // Special case. // if ( level_max == 0 ) { point_num = 1; return point_num; } // // The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. // // The normal definition of LEVEL_MIN: // // level_min = max ( 0, level_max + 1 - dim_num ) // // Our somewhat artificial temporary local definition of LEVEL_MIN: // if ( dim_num == 1 ) { level_min = level_max; point_num = 1; } else { level_min = 0; point_num = 0; } level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_open ( dim_num, level_1d, order_1d ); 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 ( 1 < order_1d[dim] ) { order_1d[dim] = order_1d[dim] - 1; } } point_num = point_num + i4vec_product ( dim_num, order_1d ); if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; return point_num; } //****************************************************************************80 void lg_abscissa ( int dim_num, int point_num, int grid_index[], int grid_base[], double grid_point[] ) //****************************************************************************80 // // Purpose: // // LG_ABSCISSA sets abscissas for multidimensional Gauss-Laguerre quadrature. // // Discussion: // // The "nesting" as it occurs for Gauss-Laguerre sparse grids simply // involves the use of a specified set of permissible orders for the // rule. // // The X array lists the (complete) Gauss-Legendre abscissas for rules // of order 1, 3, 7, 15, 31, 63 or 127, in order. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the spatial dimension. // // Input, int POINT_NUM, the number of points. // // Input, int GRID_INDEX[DIM_NUM*POINT_NUM], the index of the abscissa // from the rule, for each dimension and point. // // Input, int GRID_BASE[DIM_NUM], the number of points used in the // rule for a given dimension. // // Output, double GRID_POINT[DIM_NUM], the grid points of abscissas. // { int dim; int level; int point; int pointer; int skip[8] = { 0, 1, 4, 11, 26, 57, 120, 247 }; double x[247] = { 1.0E+00, 0.415774556783479083311533873128E+00, 0.229428036027904171982205036136E+01, 0.628994508293747919686641576551E+01, 0.193043676560362413838247885004E+00, 0.102666489533919195034519944317E+01, 0.256787674495074620690778622666E+01, 0.490035308452648456810171437810E+01, 0.818215344456286079108182755123E+01, 0.127341802917978137580126424582E+02, 0.193957278622625403117125820576E+02, 0.933078120172818047629030383672E-01, 0.492691740301883908960101791412E+00, 0.121559541207094946372992716488E+01, 0.226994952620374320247421741375E+01, 0.366762272175143727724905959436E+01, 0.542533662741355316534358132596E+01, 0.756591622661306786049739555812E+01, 0.101202285680191127347927394568E+02, 0.131302824821757235640991204176E+02, 0.166544077083299578225202408430E+02, 0.207764788994487667729157175676E+02, 0.256238942267287801445868285977E+02, 0.314075191697539385152432196202E+02, 0.385306833064860094162515167595E+02, 0.480260855726857943465734308508E+02, 0.45901947621108290743496080275224E-01, 0.24198016382477204890408974151714E+00, 0.59525389422235073707330165005414E+00, 1.1066894995329987162111308789792E+00, 1.7775956928747727211593727482675E+00, 2.6097034152566806503893375925315E+00, 3.6051968023400442698805817554243E+00, 4.7667470844717611313629127271123E+00, 6.0975545671817409269925429328463E+00, 7.6014009492331374229360106942867E+00, 9.2827143134708894182536695297710E+00, 11.146649755619291358993815629587E+00, 13.199189576244998522464925028637E+00, 15.447268315549310075809325891801E+00, 17.898929826644757646725793817752E+00, 20.563526336715822170743048968779E+00, 23.451973482011858591050255575933E+00, 26.577081352118260459975876986478E+00, 29.953990872346445506951917840024E+00, 33.600759532902202735410313885784E+00, 37.539164407330440882887902558001E+00, 41.795830870182219981347945853330E+00, 46.403866806411123136029227604386E+00, 51.405314476797755161861461088395E+00, 56.854992868715843620511922055660E+00, 62.826855908786321453677523304806E+00, 69.425277191080345623322251656443E+00, 76.807047763862732837609972285484E+00, 85.230358607545669169387065607043E+00, 95.188939891525629981308606853957E+00, 107.95224382757871475002440117666E+00, 0.22768893732576153785994330248562E-01, 0.11998325242727824715771416426383E+00, 0.29494185444770149577427738517405E+00, 0.54779087896237725363865073775856E+00, 0.87869061179931901673895567052285E+00, 1.2878464335919706302309207788611E+00, 1.7755123815388553763979463268728E+00, 2.3419925567085989256055628337716E+00, 2.9876423223246473939976731053629E+00, 3.7128695992018000346299637413422E+00, 4.5181363349503584391105568561550E+00, 5.4039601781825946286902599782736E+00, 6.3709163787865330220392250891777E+00, 7.4196399339311711154888493199004E+00, 8.5508280008403328312589048722235E+00, 9.7652425999245366807004592977996E+00, 11.063713635140661736220550410604E+00, 12.447142262356492749798687569289E+00, 13.916504641057818562912967008183E+00, 15.472856110036296424777143607779E+00, 17.117335833863588753116900303886E+00, 18.851171974154856850873483787506E+00, 20.675687448056515660377265667433E+00, 22.592306346311528381292277759986E+00, 24.602561094972638883700642760037E+00, 26.708100458737343969779087998829E+00, 28.910698500451382640177718103234E+00, 31.212264631175912885477773820802E+00, 33.614854909101154836598842888345E+00, 36.120684774484823056306328740825E+00, 38.732143442933582145626041607663E+00, 41.451810222318741191114726181363E+00, 44.282473071479233839358857134636E+00, 47.227149784295686898935095231536E+00, 50.289112264240695761749021839419E+00, 53.471914456788652808348280619542E+00, 56.779424636342062213099781057119E+00, 60.215862909019862886417550114424E+00, 63.785845004235974631701139601836E+00, 67.494433702293885830374325695045E+00, 71.347199604295266286654803376075E+00, 75.350293425653234254290504744279E+00, 79.510532629986309149555391354778E+00, 83.835506080872257843339817658508E+00, 88.333701570354369086112766326498E+00, 93.014662728558547405303399037100E+00, 97.889184147578140043386727677112E+00, 102.96955690741381650783952746778E+00, 108.26988161961595392226350967206E+00, 113.80647350287462738934485955901E+00, 119.59839538830458666962452963285E+00, 125.66817255856119431291196303280E+00, 132.04277272091165746585590583045E+00, 138.75498418103789078167590567526E+00, 145.84541318313540358283994248439E+00, 153.36548459497863623710815962660E+00, 161.38215194813761243562172669592E+00, 169.98570600665839438795175301156E+00, 179.30366247401580910251827858515E+00, 189.52789596532475473668721332981E+00, 200.97521159924656741628671841018E+00, 214.25368536638788642698056296400E+00, 230.93465747089703971246562985079E+00, 0.11339635298518611691893169631306E-01, 0.59749753435726620281348237057387E-01, 0.14685098690746167612388223687431E+00, 0.27267590735859553131378008278900E+00, 0.43724600644192665554577035869932E+00, 0.64058688222566929533576416399983E+00, 0.88272968639058364481487653650042E+00, 1.1637114160166537661560584700951E+00, 1.4835750152834613891313584861012E+00, 1.8423694351613565380686320809853E+00, 2.2401496839579024244513315656522E+00, 2.6769768780141303692167869961238E+00, 3.1529182957082825565771508308846E+00, 3.6680474360304752540226339926515E+00, 4.2224440823301888455977876667425E+00, 4.8161943715870502475665535087286E+00, 5.4493908694559416755862178908416E+00, 6.1221326512997254193944584763155E+00, 6.8345253894122668112237994973336E+00, 7.5866814466367472174205986836847E+00, 8.3787199765932725254842120659452E+00, 9.2107670307426558777922506102445E+00, 10.082955672528643809166439353647E+00, 10.995426098858125429803147358780E+00, 11.948325769197725997610605127857E+00, 12.941809542585531053723381098192E+00, 13.976039822878506520014405668679E+00, 15.051186712579523631574796365435E+00, 16.167428175612852922977395051768E+00, 17.324950209443673446561163712616E+00, 18.523947026965688560811711309349E+00, 19.764621248611504104071669386884E+00, 21.047184105173183606877044020054E+00, 22.371855651855542817648123918101E+00, 23.738864994122497183652313788712E+00, 25.148450525937368234077278385644E+00, 26.600860181041749607253384279755E+00, 28.096351697964619201753961292129E+00, 29.635192899504178910610227138642E+00, 31.217661987479759144214467152615E+00, 32.844047853610430460522951341338E+00, 34.514650407441149149105635947422E+00, 36.229780922306804019615388508885E+00, 37.989762400399956435968780140278E+00, 39.794929958089961778396437141707E+00, 41.645631232730180705153990897484E+00, 43.542226812286859549950892993822E+00, 45.485090689228791137996151336673E+00, 47.474610740231964719468766599146E+00, 49.511189233379087716728884584381E+00, 51.595243364671244443182771266934E+00, 53.727205825819316758288140069145E+00, 55.907525405447553305830605991732E+00, 58.136667626022439197077526025660E+00, 60.415115419018590295707192053805E+00, 62.743369841051809700207126742685E+00, 65.121950833949996311956025417139E+00, 67.551398031997886314411872443149E+00, 70.032271619884584511229871192030E+00, 72.565153245206849090888669416801E+00, 75.150646989739935299354362325096E+00, 77.789380404085816000647405462136E+00, 80.482005610750729205803962926758E+00, 83.229200481195914886796120019048E+00, 86.031669892953582966798238732643E+00, 88.890147073512051099652518544282E+00, 91.805395038358177994971250170499E+00, 94.778208131331583205387031034825E+00, 97.809413676305116411054110115424E+00, 100.89987375017285940371939762172E+00, 104.05048708821598934704076845022E+00, 107.26219113414600428423116401414E+00, 110.53596424851500530602771351277E+00, 113.87282809075839485348376187652E+00, 117.27385019192517774095477886379E+00, 120.74014673718880106173978002719E+00, 124.27288557955698354259506446928E+00, 127.87328950885942645093841745425E+00, 131.54263980314366921809377742137E+00, 135.28228009311836970132738106369E+00, 139.09362057432970013964422086977E+00, 142.97814260643601776808227753574E+00, 146.93740374437366549441080969072E+00, 150.97304325252187127492511437460E+00, 155.08678816034612572229641420609E+00, 159.28045992663288235401956989889E+00, 163.55598178957571104015967182053E+00, 167.91538689194360134245547184721E+00, 172.36082728473812536838156191681E+00, 176.89458392960192176311674993508E+00, 181.51907784036813069227528834025E+00, 186.23688252828112373861202530357E+00, 191.05073794450929196790836610789E+00, 195.96356614879879837839002542988E+00, 200.97848897600025153696475526130E+00, 206.09884802468871112127283042753E+00, 211.32822735671655260572377256981E+00, 216.67047937658230323477089465777E+00, 222.12975445929687246267304963754E+00, 227.71053502072232419089132431317E+00, 233.41767488282602453367775322563E+00, 239.25644498830308620018749667089E+00, 245.23258677871567172531254018984E+00, 251.35237488718128030005500991754E+00, 257.62269123792061413076191882313E+00, 264.05111322908240551754377241831E+00, 270.64601945722796749299111718606E+00, 277.41671750163651071798388218104E+00, 284.37359974220870326674402873120E+00, 291.52833521346495719581282021650E+00, 298.89410837028248600878895615414E+00, 306.48591978262611320418112423947E+00, 314.32096986471177487400007507615E+00, 322.41915589128679683349440361344E+00, 330.80372663802405651933847334878E+00, 339.50216127832433747735367595958E+00, 348.54737559472697355480761787441E+00, 357.97942028029845454049007443090E+00, 367.84794520076004578858341422871E+00, 378.21590623135532818332979188889E+00, 389.16539141251004101579475325153E+00, 400.80729331451702589996361286427E+00, 413.29853681779384418008260081859E+00, 426.87579153663675538288509017051E+00, 441.93085485310841412460309271842E+00, 459.21804639888429981971267313224E+00, 480.69378263388373859704269229304E+00 }; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_base[dim] < 1 ) { cout << "\n"; cout << "LG_ABSCISSA - Fatal error!\n"; cout << " Some base values are less than 1.\n"; exit ( 1 ); } } for ( dim = 0; dim < dim_num; dim++ ) { if ( 127 < grid_base[dim] ) { cout << "\n"; cout << "LG_ABSCISSA - Fatal error!\n"; cout << " Some base values are greater than 127.\n"; exit ( 1 ); } } for ( point = 0; point < point_num; point++ ) { for ( dim = 0; dim < dim_num; dim++ ) { level = i4_log_2 ( grid_base[dim] + 1 ) - 1; pointer = skip[level] + grid_index[dim+point*dim_num]; if ( pointer < 1 || 247 < pointer ) { cout << "\n"; cout << "LG_ABSCISSA - Fatal error!\n"; cout << " POINTER out of bounds.\n"; cout << " POINTER = " << pointer << "\n"; cout << " POINT = " << point << "\n"; cout << " DIM = " << dim << "\n"; cout << " GRID_BASE = " << grid_base[dim] << "\n"; cout << " LEVEL = " << level << "\n"; cout << " GRID_INDEX = " << grid_index[dim+point*dim_num] << "\n"; exit ( 1 ); } grid_point[dim+point*dim_num] = x[pointer-1]; } } return; } //****************************************************************************80 double *lg_weights ( int order ) //****************************************************************************80 // // Purpose: // // LG_WEIGHTS returns weights for certain Gauss-Laguerre quadrature rules. // // Discussion: // // The allowed orders are 1, 3, 7, 15, 31, 63 and 127. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2007 // // Author: // // John Burkardt // // Reference: // // Milton Abramowitz, Irene Stegun, // Handbook of Mathematical Functions, // National Bureau of Standards, 1964, // ISBN: 0-486-61272-4, // LC: QA47.A34. // // Arthur Stroud, Don Secrest, // Gaussian Quadrature Formulas, // Prentice Hall, 1966, // LC: QA299.4G3S7. // // Parameters: // // Input, int ORDER, the order of the rule. // ORDER must be 1, 3, 7, 15, 31, 63 or 127. // // Output, double WEIGHT[ORDER], the weights. // The weights are positive, symmetric and should sum to 1. // { double *weight; weight = new double[order]; if ( order == 1 ) { weight[1-1] = 1.0E+00; } else if ( order == 3 ) { weight[1-1] = 0.711093009929173015449590191143E+00; weight[2-1] = 0.278517733569240848801444888457E+00; weight[3-1] = 0.103892565015861357489649204007E-01; } else if ( order == 7 ) { weight[1-1] = 0.409318951701273902130432880018E+00; weight[2-1] = 0.421831277861719779929281005417E+00; weight[3-1] = 0.147126348657505278395374184637E+00; weight[4-1] = 0.206335144687169398657056149642E-01; weight[5-1] = 0.107401014328074552213195962843E-02; weight[6-1] = 0.158654643485642012687326223234E-04; weight[7-1] = 0.317031547899558056227132215385E-07; } else if ( order == 15 ) { weight[1-1] = 0.218234885940086889856413236448E+00; weight[2-1] = 0.342210177922883329638948956807E+00; weight[3-1] = 0.263027577941680097414812275022E+00; weight[4-1] = 0.126425818105930535843030549378E+00; weight[5-1] = 0.402068649210009148415854789871E-01; weight[6-1] = 0.856387780361183836391575987649E-02; weight[7-1] = 0.121243614721425207621920522467E-02; weight[8-1] = 0.111674392344251941992578595518E-03; weight[9-1] = 0.645992676202290092465319025312E-05; weight[10-1] = 0.222631690709627263033182809179E-06; weight[11-1] = 0.422743038497936500735127949331E-08; weight[12-1] = 0.392189726704108929038460981949E-10; weight[13-1] = 0.145651526407312640633273963455E-12; weight[14-1] = 0.148302705111330133546164737187E-15; weight[15-1] = 0.160059490621113323104997812370E-19; } else if ( order == 31 ) { weight[ 1-1] = 0.11252789550372583820847728082801E+00; weight[ 2-1] = 0.21552760818089123795222505285045E+00; weight[ 3-1] = 0.23830825164569654731905788089234E+00; weight[ 4-1] = 0.19538830929790229249915303390711E+00; weight[ 5-1] = 0.12698283289306190143635272904602E+00; weight[ 6-1] = 0.67186168923899300670929441993508E-01; weight[ 7-1] = 0.29303224993879487404888669311974E-01; weight[ 8-1] = 0.10597569915295736089529380314433E-01; weight[ 9-1] = 0.31851272582386980320974842433019E-02; weight[ 10-1] = 0.79549548307940382922092149012477E-03; weight[ 11-1] = 0.16480052126636687317862967116412E-03; weight[ 12-1] = 0.28229237864310816393860971468993E-04; weight[ 13-1] = 0.39802902551008580387116174900106E-05; weight[ 14-1] = 0.45931839841801061673729694510289E-06; weight[ 15-1] = 0.43075545187731100930131457465897E-07; weight[ 16-1] = 0.32551249938271570855175749257884E-08; weight[ 17-1] = 0.19620246675410594996247151593142E-09; weight[ 18-1] = 0.93190499086617587129534716431331E-11; weight[ 19-1] = 0.34377541819411620520312597898311E-12; weight[ 20-1] = 0.96795247130446716997405035776206E-14; weight[ 21-1] = 0.20368066110115247398010624219291E-15; weight[ 22-1] = 0.31212687280713526831765358632585E-17; weight[ 23-1] = 0.33729581704161052453395678308350E-19; weight[ 24-1] = 0.24672796386616696011038363242541E-21; weight[ 25-1] = 0.11582201904525643634834564576593E-23; weight[ 26-1] = 0.32472922591425422434798022809020E-26; weight[ 27-1] = 0.49143017308057432740820076259666E-29; weight[ 28-1] = 0.34500071104808394132223135953806E-32; weight[ 29-1] = 0.87663710117162041472932760732881E-36; weight[ 30-1] = 0.50363643921161490411297172316582E-40; weight[ 31-1] = 0.19909984582531456482439549080330E-45; } else if ( order == 63 ) { weight[ 1-1] = 0.57118633213868979811587283390476E-01; weight[ 2-1] = 0.12067476090640395283319932036351E+00; weight[ 3-1] = 0.15925001096581873723870561096472E+00; weight[ 4-1] = 0.16875178327560799234596192963585E+00; weight[ 5-1] = 0.15366641977668956696193711310131E+00; weight[ 6-1] = 0.12368770614716481641086652261948E+00; weight[ 7-1] = 0.89275098854848671545279150057422E-01; weight[ 8-1] = 0.58258485446105944957571825725160E-01; weight[ 9-1] = 0.34546657545992580874717085812508E-01; weight[ 10-1] = 0.18675685985714656798286552591203E-01; weight[ 11-1] = 0.92233449044093536528490075241649E-02; weight[ 12-1] = 0.41671250684839592762582663470209E-02; weight[ 13-1] = 0.17238120299900582715386728541955E-02; weight[ 14-1] = 0.65320845029716311169340559359043E-03; weight[ 15-1] = 0.22677644670909586952405173207471E-03; weight[ 16-1] = 0.72127674154810668410750270234861E-04; weight[ 17-1] = 0.21011261180466484598811536851241E-04; weight[ 18-1] = 0.56035500893357212749181536071292E-05; weight[ 19-1] = 0.13673642785604888017836641282292E-05; weight[ 20-1] = 0.30507263930195817240736097189550E-06; weight[ 21-1] = 0.62180061839309763559981775409241E-07; weight[ 22-1] = 0.11566529551931711260022448996296E-07; weight[ 23-1] = 0.19614588267565478081534781863335E-08; weight[ 24-1] = 0.30286171195709411244334756404054E-09; weight[ 25-1] = 0.42521344539400686769012963452599E-10; weight[ 26-1] = 0.54202220578073819334698791381873E-11; weight[ 27-1] = 0.62627306838597672554166850420603E-12; weight[ 28-1] = 0.65474443156573322992307089591924E-13; weight[ 29-1] = 0.61815575808729181846302500000047E-14; weight[ 30-1] = 0.52592721363507381404263991342633E-15; weight[ 31-1] = 0.40230920092646484015391506025408E-16; weight[ 32-1] = 0.27600740511819536505013824207729E-17; weight[ 33-1] = 0.16936946756968296053322009855265E-18; weight[ 34-1] = 0.92689146872177087314963772462726E-20; weight[ 35-1] = 0.45093739060365632939780140603959E-21; weight[ 36-1] = 0.19435162876132376573629962695374E-22; weight[ 37-1] = 0.73926270895169207037999639194513E-24; weight[ 38-1] = 0.24714364154434632615980126000066E-25; weight[ 39-1] = 0.72288649446741597655145390616476E-27; weight[ 40-1] = 0.18407617292614039362985209905608E-28; weight[ 41-1] = 0.40583498566841960105759537058880E-30; weight[ 42-1] = 0.77000496416438368114463925286343E-32; weight[ 43-1] = 0.12488505764999334328843314866038E-33; weight[ 44-1] = 0.17185000226767010697663950619912E-35; weight[ 45-1] = 0.19896372636672396938013975755522E-37; weight[ 46-1] = 0.19199671378804058267713164416870E-39; weight[ 47-1] = 0.15278588285522166920459714708240E-41; weight[ 48-1] = 0.99054752688842142955854138884590E-44; weight[ 49-1] = 0.51597523673029211884228858692990E-46; weight[ 50-1] = 0.21249846664084111245693912887783E-48; weight[ 51-1] = 0.67903852766852910591172042494884E-51; weight[ 52-1] = 0.16466654148296177467908300517887E-53; weight[ 53-1] = 0.29509065402691055027053659375033E-56; weight[ 54-1] = 0.37838420647571051984882241014675E-59; weight[ 55-1] = 0.33358130068542431878174667995217E-62; weight[ 56-1] = 0.19223461022273880981363303073329E-65; weight[ 57-1] = 0.67812696961083016872779388922288E-69; weight[ 58-1] = 0.13404752802440604607620468935693E-72; weight[ 59-1] = 0.13109745101805029757648048223928E-76; weight[ 60-1] = 0.52624863881401787388694579143866E-81; weight[ 61-1] = 0.63780013856587414257760666006511E-86; weight[ 62-1] = 0.12997078942372924566347473916943E-91; weight[ 63-1] = 0.10008511496968754063443740168421E-98; } else if ( order == 127 ) { weight[ 1-1] = 0.28773246692000124355770010301506E-01; weight[ 2-1] = 0.63817468175134649363480949265236E-01; weight[ 3-1] = 0.91919669721570571389864194652717E-01; weight[ 4-1] = 0.11054167914413766381245463002967E+00; weight[ 5-1] = 0.11879771633375850188328329422643E+00; weight[ 6-1] = 0.11737818530052695148804451630074E+00; weight[ 7-1] = 0.10819305984180551488335145581193E+00; weight[ 8-1] = 0.93827075290489628080377261401107E-01; weight[ 9-1] = 0.76966450960588843995822485928431E-01; weight[ 10-1] = 0.59934903912939714332570730063476E-01; weight[ 11-1] = 0.44417742073889001371708316272923E-01; weight[ 12-1] = 0.31385080966252320983009372215062E-01; weight[ 13-1] = 0.21172316041924506411370709025015E-01; weight[ 14-1] = 0.13650145364230541652171185564626E-01; weight[ 15-1] = 0.84172852710599172279366657385445E-02; weight[ 16-1] = 0.49674990059882760515912858620175E-02; weight[ 17-1] = 0.28069903895001884631961957446400E-02; weight[ 18-1] = 0.15192951003941952460445341057817E-02; weight[ 19-1] = 0.78789028751796084086217287140548E-03; weight[ 20-1] = 0.39156751064868450584507324648999E-03; weight[ 21-1] = 0.18652434268825860550093566260060E-03; weight[ 22-1] = 0.85173160415576621908809828160247E-04; weight[ 23-1] = 0.37285639197853037712145321577724E-04; weight[ 24-1] = 0.15648416791712993947447805296768E-04; weight[ 25-1] = 0.62964340695224829035692735524979E-05; weight[ 26-1] = 0.24288929711328724574541379938222E-05; weight[ 27-1] = 0.89824607890051007201922871545035E-06; weight[ 28-1] = 0.31844174740760353710742966328091E-06; weight[ 29-1] = 0.10821272905566839211861807542741E-06; weight[ 30-1] = 0.35245076750635536015902779085340E-07; weight[ 31-1] = 0.11001224365719347407063839761738E-07; weight[ 32-1] = 0.32904079616717932125329343003261E-08; weight[ 33-1] = 0.94289145237889976419772700772988E-09; weight[ 34-1] = 0.25882578904668318184050195309296E-09; weight[ 35-1] = 0.68047437103370762630942259017560E-10; weight[ 36-1] = 0.17131398805120837835399564475632E-10; weight[ 37-1] = 0.41291744524052865469443922304935E-11; weight[ 38-1] = 0.95264189718807273220707664873469E-12; weight[ 39-1] = 0.21032604432442425932962942047474E-12; weight[ 40-1] = 0.44427151938729352860940434285789E-13; weight[ 41-1] = 0.89760500362833703323319846405449E-14; weight[ 42-1] = 0.17341511407769287074627948346848E-14; weight[ 43-1] = 0.32028099548988356631494379835210E-15; weight[ 44-1] = 0.56531388950793682022660742095189E-16; weight[ 45-1] = 0.95329672799026591234588044025896E-17; weight[ 46-1] = 0.15353453477310142565288509437552E-17; weight[ 47-1] = 0.23608962179467365686057842132176E-18; weight[ 48-1] = 0.34648742794456611332193876653230E-19; weight[ 49-1] = 0.48515241897086461320126957663545E-20; weight[ 50-1] = 0.64786228633519813428137373790678E-21; weight[ 51-1] = 0.82476020965403242936448553126316E-22; weight[ 52-1] = 0.10005361880214719793491658282977E-22; weight[ 53-1] = 0.11561395116207304954233181263632E-23; weight[ 54-1] = 0.12719342731167922655612134264961E-24; weight[ 55-1] = 0.13316584714165372967340004160814E-25; weight[ 56-1] = 0.13261218454678944033646108509198E-26; weight[ 57-1] = 0.12554995447643949807286074138324E-27; weight[ 58-1] = 0.11294412178579462703240913107219E-28; weight[ 59-1] = 0.96491020279562119228500608131696E-30; weight[ 60-1] = 0.78241846768302099396733076955632E-31; weight[ 61-1] = 0.60181503542219626658249939076636E-32; weight[ 62-1] = 0.43882482704961741551510518054138E-33; weight[ 63-1] = 0.30314137647517256304035802501863E-34; weight[ 64-1] = 0.19826016543944539545224676057020E-35; weight[ 65-1] = 0.12267623373665926559013654872402E-36; weight[ 66-1] = 0.71763931692508888943812834967620E-38; weight[ 67-1] = 0.39659378833836963584113716149270E-39; weight[ 68-1] = 0.20688970553868040099581951696677E-40; weight[ 69-1] = 0.10179587017979517245268418427523E-41; weight[ 70-1] = 0.47200827745986374625714293679649E-43; weight[ 71-1] = 0.20606828985553374825744353490744E-44; weight[ 72-1] = 0.84627575907305987245899032156188E-46; weight[ 73-1] = 0.32661123687088798658026998931647E-47; weight[ 74-1] = 0.11833939207883162380564134612682E-48; weight[ 75-1] = 0.40211209123895013807243250164050E-50; weight[ 76-1] = 0.12799824394111125389430292847476E-51; weight[ 77-1] = 0.38123877747548846504399051365162E-53; weight[ 78-1] = 0.10612057542701156767898551949650E-54; weight[ 79-1] = 0.27571446947200403594113572720812E-56; weight[ 80-1] = 0.66772544240928492881306904862856E-58; weight[ 81-1] = 0.15052438383868234954068178600268E-59; weight[ 82-1] = 0.31538986800113758526689068500772E-61; weight[ 83-1] = 0.61326614299483180785237418887960E-63; weight[ 84-1] = 0.11048510030324810567549119229368E-64; weight[ 85-1] = 0.18410563538091348076979665543900E-66; weight[ 86-1] = 0.28323926570052832195543883237652E-68; weight[ 87-1] = 0.40154409843763655508670978777418E-70; weight[ 88-1] = 0.52351530215683708779772201956106E-72; weight[ 89-1] = 0.62634476665005100555787696642851E-74; weight[ 90-1] = 0.68612210535666530365348093803922E-76; weight[ 91-1] = 0.68651298840956019297134099761855E-78; weight[ 92-1] = 0.62581388433728084867318704240915E-80; weight[ 93-1] = 0.51833271237514904046803469968027E-82; weight[ 94-1] = 0.38893621571918443533108973497673E-84; weight[ 95-1] = 0.26357711379476932781525533730623E-86; weight[ 96-1] = 0.16078851293917979699005509638883E-88; weight[ 97-1] = 0.87978042070968939637972577886624E-91; weight[ 98-1] = 0.43013405077495109903408697802188E-93; weight[ 99-1] = 0.18713435881342838527144321803729E-95; weight[100-1] = 0.72125744708060471675805761366523E-98; weight[101-1] = 0.24508746062177874383231742333023E-100; weight[102-1] = 0.73042094619470875777647865078327E-103; weight[103-1] = 0.18983290818383463537886818579820E-105; weight[104-1] = 0.42757400244246684123093264825902E-108; weight[105-1] = 0.82894681420515755691423485228897E-111; weight[106-1] = 0.13729432219324400013067050156048E-113; weight[107-1] = 0.19265464126404973222043166489406E-116; weight[108-1] = 0.22693344503301354826140809941334E-119; weight[109-1] = 0.22209290603717355061909071271535E-122; weight[110-1] = 0.17851087685544512662856555121755E-125; weight[111-1] = 0.11630931990387164467431190485525E-128; weight[112-1] = 0.60524443584652392290952805077893E-132; weight[113-1] = 0.24729569115063528647628375096400E-135; weight[114-1] = 0.77789065006489410364997205809045E-139; weight[115-1] = 0.18409738662712607039570678274636E-142; weight[116-1] = 0.31900921131079114970179071968597E-146; weight[117-1] = 0.39179487139174199737617666077555E-150; weight[118-1] = 0.32782158394188697053774429820559E-154; weight[119-1] = 0.17793590713138888062819640128739E-158; weight[120-1] = 0.58882353408932623157467835381214E-163; weight[121-1] = 0.10957236509071169877747203273886E-167; weight[122-1] = 0.10281621114867000898285076975760E-172; weight[123-1] = 0.41704725557697758145816510853967E-178; weight[124-1] = 0.58002877720316101774638319601971E-184; weight[125-1] = 0.18873507745825517106171619101120E-190; weight[126-1] = 0.69106601826730911682786705950895E-198; weight[127-1] = 0.43506813201105855628383313334402E-207; } else { cout << "\n"; cout << "LG_WEIGHTS - Fatal error!\n"; cout << " Illegal value of ORDER = " << order << "\n"; cout << " Legal values are 1, 3, 7, 15, 31, 63 and 127.\n"; exit ( 1 ); } return weight; } //****************************************************************************80 double monomial_integral_hermite ( int dim_num, int expon[] ) //****************************************************************************80 // // Purpose: // // MONOMIAL_INTEGRAL_HERMITE integrates a Hermite mononomial. // // Discussion: // // H(d,n) = Integral ( -Infinity < x < Infinity ) // x1^n1 * x2^n2...*xd^nd * exp(-x1^2-x2^2...-xd^2 ) dx // // H(d,n) is 0 if any n(i) odd. // // H(d,n) = product ( 1 <= i <= d ) // ( (n(i)-1)!! * sqrt(pi) / 2^(n(i)/2) for all n(i) even. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 October 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the dimension of the integral. // // Input, int EXPON[DIM_NUM], the order of the integral. // 0 <= EXPON(1:DIM_NUM). // // Output, double HERMITE_INTEGRAL, the value of the integral. // { int dim; double pi = 3.141592653589793; double value; for ( dim = 0; dim < dim_num; dim++ ) { if ( expon[dim] < 0 ) { value = - r8_huge ( ); return value; } } for ( dim = 0; dim < dim_num; dim++ ) { if ( ( expon[dim] % 2 ) == 1 ) { value = 0.0; return value; } } value = 1.0; for ( dim = 0; dim < dim_num; dim++ ) { value = value * r8_factorial2 ( expon[dim] - 1 ) * sqrt ( pi ) / ( double ) i4_power ( 2, expon[dim] / 2 ); } return value; } //****************************************************************************80 double monomial_integral_laguerre ( int dim_num, int expon[] ) //****************************************************************************80 // // Purpose: // // MONOMIAL_INTEGRAL_LAGUERRE integrates a Laguerre monomial. // // Discussion: // // L(1,n) = Integral ( 0 <= x < Infinity ) x^n exp ( -x ) dx // = n! // // L(d,n) = Integral ( 0 <= x(i) < Infinity ) // x1^n1 * x2^n2...*xd^nd * exp(-x1-x2...-xd ) dx // = Product ( n(i)! ). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the dimension of the integral. // // Input, int EXPON[DIM_NUM], the order of the integral. // 0 <= EXPON(1:DIM_NUM). // // Output, double MONOMIAL_INTEGRAL_LAGUERRE, the value of the integral. // { int dim; double value; value = 1.0; for ( dim = 0; dim < dim_num; dim++ ) { value = value * r8_factorial ( expon[dim] ); } return value; } //****************************************************************************80 double monomial_integral_legendre ( int dim_num, int expon[] ) //****************************************************************************80 // // Purpose: // // MONOMIAL_INTEGRAL_LEGENDRE integrates a Legendre monomial. // // Discussion: // // This routine returns the exact value of a multidimensional Legendre // type integral: // // integral ( -1 <= x(1:n) <= +1 ) f(x) dx // // where f(x) is a monomial of the form: // // product ( 1 <= dim <= dim_num ) x(dim)^expon(dim) // // and the exponents are nonnegative integers. Note that the combination // 0^0 is treated as 1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 March 2008 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the spatial dimension. // // Input, int EXPON[DIM_NUM], the exponents. // // Output, double MONOMIAL_INTEGRAL_LEGENDRE, the value of the integral // of the monomial. // { int dim; double value; value = 0.0; for ( dim = 0; dim < dim_num; dim++ ) { if ( ( expon[dim] % 2 ) == 1 ) { return value; } } value = 1.0; for ( dim = 0; dim < dim_num; dim++ ) { value = value * 2.0 / ( double ) ( expon[dim] + 1 ); } return value; } //****************************************************************************80 double monomial_quadrature ( int dim_num, int expon[], int point_num, double weight[], double x[], int rule ) //****************************************************************************80 // // Purpose: // // MONOMIAL_QUADRATURE applies a quadrature rule to a monomial. // // 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 EXPON[DIM_NUM], the exponents. // // Input, int POINT_NUM, the number of points in the rule. // // Input, double WEIGHT[POINT_NUM], the quadrature weights. // // Input, double X[DIM_NUM*POINT_NUM], the quadrature points. // // 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 MONOMIAL_QUADRATURE, the quadrature error. // { double exact; int point; double quad; double quad_error; double scale; double *value; // // Get the exact value of the integral of the unscaled monomial. // if ( 1 <= rule && rule <= 5 ) { exact = monomial_integral_legendre ( dim_num, expon ); } else if ( rule == 6 ) { exact = monomial_integral_hermite ( dim_num, expon ); } else if ( rule == 7 ) { exact = monomial_integral_laguerre ( dim_num, expon ); } else { cout << "\n"; cout << "MONOMIAL_QUADRATURE - Fatal error!\n"; cout << " Unrecognized value of RULE.\n"; exit ( 1 ); } // // Evaluate the monomial at the quadrature points. // value = monomial_value ( dim_num, point_num, x, expon ); // // Compute the quadrature sum. // quad = 0.0; for ( point = 0; point < point_num; point++ ) { quad = quad + weight[point] * value[point]; } // // Absolute error if EXACT = 0, relative error otherwise: // if ( exact == 0.0 ) { quad_error = r8_abs ( quad - exact ); } else { quad_error = r8_abs ( quad - exact ) / r8_abs ( exact ); } delete [] value; return quad_error; } //****************************************************************************80 double *monomial_value ( int dim_num, int point_num, double x[], int expon[] ) //****************************************************************************80 // // Purpose: // // MONOMIAL_VALUE evaluates a monomial. // // Discussion: // // This routine evaluates a monomial of the form // // product ( 1 <= dim <= dim_num ) x(dim)^expon(dim) // // where the exponents are nonnegative integers. Note that // if the combination 0^0 is encountered, it should be treated // as 1. // // 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 POINT_NUM, the number of points at which the // monomial is to be evaluated. // // Input, double X[DIM_NUM*POINT_NUM], the point coordinates. // // Input, int EXPON[DIM_NUM], the exponents. // // Output, double MONOMIAL_VALUE[POINT_NUM], the value of the monomial. // { int dim; int point; double *value; value = new double[point_num]; for ( point = 0; point < point_num; point++ ) { value[point] = 1.0; } for ( dim = 0; dim < dim_num; dim++ ) { if ( 0 != expon[dim] ) { for ( point = 0; point < point_num; point++ ) { value[point] = value[point] * pow ( x[dim+point*dim_num], expon[dim] ); } } } return value; } //****************************************************************************80 int *multigrid_index_cfn ( int dim_num, int order_1d[], int order_nd ) //****************************************************************************80 // // Purpose: // // MULTIGRID_INDEX_CFN indexes a sparse grid based on CFN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of CLOSED FULLY NESTED 1D quadrature rules. // // CFN rules include Clenshaw Curtis rules. // // For dimension DIM, the second index of INDX may vary from // 0 to ORDER_1D(DIM)-1. // // 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 ORDER_1D[DIM_NUM], the order of the // rule in each dimension. // // Input, int ORDER_ND, the product of the entries of ORDER_1D. // // Output, int INDX[DIM_NUM*ORDER_ND], the indices of the points in // the grid. The second dimension of this array is equal to the // product of the entries of ORDER_1D. // { int *a; int dim; bool more; int p; int *indx; indx = new int[dim_num*order_nd]; a = new int[dim_num]; more = false; p = 0; for ( ; ; ) { vec_colex_next2 ( dim_num, order_1d, a, &more ); if ( !more ) { break; } for ( dim = 0; dim < dim_num; dim++ ) { indx[dim+p*dim_num] = a[dim]; } p = p + 1; } delete [] a; return indx; } //****************************************************************************80 int *multigrid_index_ofn ( int dim_num, int order_1d[], int order_nd ) //****************************************************************************80 // // Purpose: // // MULTIGRID_INDEX_OFN indexes a sparse grid based on OFN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN FULLY NESTED 1D quadrature rules. // // OFN rules include Fejer 1, Fejer 2, and Gauss Patterson rules. // // For dimension DIM, the second index of INDX may vary from // 1 to ORDER_1D(DIM). // // Modified: // // 26 March 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 of the points. // // Input, int ORDER_1D[DIM_NUM], the order of the // rule in each dimension. // // Input, int ORDER_ND, the product of the entries of ORDER_1D. // // Output, int INDX[DIM_NUM*ORDER_ND], the indices of the points in // the grid. The second dimension of this array is equal to the // product of the entries of ORDER_1D. // { int *a; int dim; bool more; int p; int *indx; indx = new int[dim_num*order_nd]; a = new int[dim_num]; more = false; p = 0; for ( ; ; ) { vec_colex_next2 ( dim_num, order_1d, a, &more ); if ( !more ) { break; } for ( dim = 0; dim < dim_num; dim++ ) { indx[dim+p*dim_num] = a[dim] + 1; } p = p + 1; } delete [] a; return indx; } //****************************************************************************80 int *multigrid_index_onn ( int dim_num, int order_1d[], int order_nd ) //****************************************************************************80 // // Purpose: // // MULTIGRID_INDEX_ONN indexes a sparse grid based on ONN 1D rules. // // Discussion: // // The sparse grid is presumed to have been created from products // of OPEN NON-NESTED 1D quadrature rules. // // ONN rules include Gauss Laguerre. // // For dimension DIM, the number of points is ORDER_1D(DIM). // // We index the points as // 1, 2, 3, ..., ORDER_1D(DIM). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 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 of the points. // // Input, int ORDER_1D[DIM_NUM], the order of the // rule in each dimension. // // Input, int ORDER_ND, the product of the entries of ORDER_1D. // // Output, int INDX[DIM_NUM*ORDER_ND], the indices of the points in // the grid. The second dimension of this array is equal to the // product of the entries of ORDER_1D. // { int *a; int dim; bool more; int p; int *indx; indx = new int[dim_num*order_nd]; a = new int[dim_num]; more = false; p = 0; for ( ; ; ) { vec_colex_next2 ( dim_num, order_1d, a, &more ); if ( !more ) { break; } // // The values of A(DIM) are between 0 and ORDER_1D(DIM)-1 = N - 1 = 2 * M. // Subtracting M sets the range to -M to +M, as we wish. // for ( dim = 0; dim < dim_num; dim++ ) { indx[dim+p*dim_num] = a[dim] + 1; } p = p + 1; } delete [] a; return indx; } //****************************************************************************80 int *multigrid_index_own ( int dim_num, int order_1d[], int order_nd ) //****************************************************************************80 // // Purpose: // // MULTIGRID_INDEX_OWN returns an indexed multidimensional grid. // // Discussion: // // For dimension DIM, the number of points is ORDER_1D[DIM]. // // We assume that ORDER_1D[DIM] is an odd number, // ORDER_1D[DIM] = N = 2 * M + 1 // so that the points have coordinates // -M/M, -(M-1)/M, ..., -1/M, 0/M, 1/M, 2/M, 3/M, ..., (M-1)/M, M/M. // and we index them as // -M, -(M-1), -1, 0, 1, 2, 3, ..., M-1, M. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 September 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 of the points. // // Input, int ORDER_1D[DIM_NUM], the order of the // rule in each dimension. // // Input, int ORDER_ND, the product of the entries of ORDER_1D. // // Output, int INDX[DIM_NUM*ORDER_ND], the indices of the points in // the grid. The second dimension of this array is equal to the // product of the entries of ORDER_1D. // { int *a; int dim; bool more; int p; int *indx; indx = new int[dim_num*order_nd]; a = new int[dim_num]; more = false; p = 0; for ( ; ; ) { vec_colex_next2 ( dim_num, order_1d, a, &more ); if ( !more ) { break; } // // The values of A(DIM) are between 0 and ORDER_1D(DIM)-1 = N - 1 = 2 * M. // Subtracting M sets the range to -M to +M, as we wish. // for ( dim = 0; dim < dim_num; dim++ ) { indx[dim+p*dim_num] = a[dim] - ( order_1d[dim] - 1 ) / 2; } p = p + 1; } delete [] a; return indx; } //****************************************************************************80 void multigrid_scale_closed ( int dim_num, int order_nd, int level_max, int level_1d[], int grid_index[] ) //****************************************************************************80 // // Purpose: // // MULTIGRID_SCALE_CLOSED renumbers a grid as a subgrid on a higher level. // // Discussion: // // This routine takes a grid associated with a given value of // LEVEL, and multiplies all the indices by a power of 2, so that // the indices reflect the position of the same points, but in // a grid of level LEVEL_MAX. // // 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 ORDER_ND, the number of points in the grid. // // Input, int LEVEL_MAX, the maximum value of LEVEL. // // Input, int LEVEL_1D[DIM_NUM], the level in each dimension. // // Input/output, int GRID_INDEX[DIM_NUM*POINT_NUM], the index // values for each grid point. On input, these indices are based in // the level for which the grid was generated; on output, the // indices are appropriate for the grid as a subgrid of a grid // of level LEVEL_MAX. // { int dim; int factor; int order; int order_max; for ( dim = 0; dim < dim_num; dim++ ) { if ( level_1d[dim] == 0 ) { if ( 0 == level_max ) { order_max = 1; } else { order_max = i4_power ( 2, level_max ) + 1; } for ( order = 0; order < order_nd; order++ ) { grid_index[dim+order*dim_num] = ( order_max - 1 ) / 2; } } else { factor = i4_power ( 2, level_max - level_1d[dim] ); for ( order = 0; order < order_nd; order++ ) { grid_index[dim+order*dim_num] = grid_index[dim+order*dim_num] * factor; } } } return; } //****************************************************************************80 void multigrid_scale_open ( int dim_num, int order_nd, int level_max, int level_1d[], int grid_index[] ) //****************************************************************************80 // // Purpose: // // MULTIGRID_SCALE_OPEN renumbers a grid as a subgrid on a higher level. // // Discussion: // // This routine takes a grid associated with a given value of // LEVEL, and multiplies all the indices by a power of 2, so that // the indices reflect the position of the same points, but in // a grid of level LEVEL_MAX. // // For an open grid, going from one level to the next, a set of indices // will be rescaled by 2*INDEX-1. // // Modified: // // 08 June 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 ORDER_ND, the number of points in the grid. // // Input, int LEVEL_MAX, the maximum value of LEVEL. // // Input, int LEVEL_1D[DIM_NUM], the level in each dimension. // // Input/output, int GRID_INDEX[DIM_NUM*POINT_NUM], the index // values for each grid point. On input, these indices are based in // the level for which the grid was generated; on output, the // indices are appropriate for the grid as a subgrid of a grid // of level LEVEL_MAX. // { int dim; int factor; int order; for ( dim = 0; dim < dim_num; dim++ ) { factor = i4_power ( 2, level_max - level_1d[dim] ); for ( order = 0; order < order_nd; order++ ) { grid_index[dim+order*dim_num] = grid_index[dim+order*dim_num] * factor; } } return; } //****************************************************************************80 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; double *w_1d; double *w_nd; 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++ ) { if ( rule == 1 ) { w_1d = cc_weights ( order_1d[dim] ); } else if ( rule == 2 ) { w_1d = f1_weights ( order_1d[dim] ); } else if ( rule == 3 ) { w_1d = f2_weights ( order_1d[dim] ); } else if ( rule == 4 ) { w_1d = gp_weights ( order_1d[dim] ); } else if ( rule == 5 ) { w_1d = gl_weights ( order_1d[dim] ); } else if ( rule == 6 ) { w_1d = gh_weights ( order_1d[dim] ); } else if ( rule == 7 ) { w_1d = lg_weights ( order_1d[dim] ); } else { cout << "\n"; cout << "PRODUCT_WEIGHTS - Fatal error!\n"; cout << " Unrecognized rule number = " << rule << "\n"; exit ( 1 ); } r8vec_direct_product2 ( dim, order_1d[dim], w_1d, dim_num, order_nd, w_nd ); delete [] w_1d; } return w_nd; } //****************************************************************************80 double r8_abs ( double x ) //****************************************************************************80 // // Purpose: // // R8_ABS returns the absolute value of an R8. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 November 2006 // // Author: // // John Burkardt // // Parameters: // // Input, double X, the quantity whose absolute value is desired. // // Output, double R8_ABS, the absolute value of X. // { double value; if ( 0.0 <= x ) { value = x; } else { value = -x; } return value; } //****************************************************************************80 double r8_choose ( int n, int k ) //****************************************************************************80 // // Purpose: // // R8_CHOOSE computes the binomial coefficient C(N,K) as an R8. // // Discussion: // // The value is calculated in such a way as to avoid overflow and // roundoff. The calculation is done in R8 arithmetic. // // The formula used is: // // C(N,K) = N! / ( K! * (N-K)! ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 March 2008 // // Author: // // John Burkardt // // Reference: // // ML Wolfson, HV Wright, // Algorithm 160: // Combinatorial of M Things Taken N at a Time, // Communications of the ACM, // Volume 6, Number 4, April 1963, page 161. // // Parameters: // // Input, int N, K, the values of N and K. // // Output, double R8_CHOOSE, the number of combinations of N // things taken K at a time. // { int i; int mn; int mx; int value; mn = i4_min ( k, n - k ); if ( mn < 0 ) { value = 0.0; } else if ( mn == 0 ) { value = 1.0; } else { mx = i4_max ( k, n - k ); value = ( double ) ( mx + 1 ); for ( i = 2; i <= mn; i++ ) { value = ( value * ( double ) ( mx + i ) ) / ( double ) i; } } return value; } //****************************************************************************80 double r8_factorial ( int n ) //****************************************************************************80 // // Purpose: // // R8_FACTORIAL computes the factorial of N. // // Discussion: // // factorial ( N ) = N! = product ( 1 <= I <= N ) I // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 January 1999 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the argument of the factorial function. // If N is less than 1, the function value is returned as 1. // // Output, double R8_FACTORIAL, the factorial of N. // { int i; double value; value = 1.0; for ( i = 1; i <= n; i++ ) { value = value * ( double ) ( i ); } return value; } //****************************************************************************80 double r8_factorial2 ( int n ) //****************************************************************************80 // // Purpose: // // R8_FACTORIAL2 computes the double factorial function. // // Discussion: // // FACTORIAL2( N ) = Product ( N * (N-2) * (N-4) * ... * 2 ) (N even) // = Product ( N * (N-2) * (N-4) * ... * 1 ) (N odd) // // Example: // // N N!! // // 0 1 // 1 1 // 2 2 // 3 3 // 4 8 // 5 15 // 6 48 // 7 105 // 8 384 // 9 945 // 10 3840 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 January 2008 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the argument of the double factorial // function. If N is less than 1, R8_FACTORIAL2 is returned as 1.0. // // Output, double R8_FACTORIAL2, the value of N!!. // { int n_copy; double value; value = 1.0; if ( n < 1 ) { return value; } n_copy = n; while ( 1 < n_copy ) { value = value * ( double ) n_copy; n_copy = n_copy - 2; } return value; } //****************************************************************************80 double r8_huge ( ) //****************************************************************************80 // // Purpose: // // R8_HUGE returns a "huge" R8. // // Discussion: // // The value returned by this function is NOT required to be the // maximum representable R8. This value varies from machine to machine, // from compiler to compiler, and may cause problems when being printed. // We simply want a "very large" but non-infinite number. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 October 2007 // // Author: // // John Burkardt // // Parameters: // // Output, double R8_HUGE, a "huge" R8 value. // { double value; value = 1.0E+30; return value; } //****************************************************************************80 double r8_mop ( int i ) //****************************************************************************80 // // Purpose: // // R8_MOP returns the I-th power of -1 as an R8 value. // // Discussion: // // An R8 is an double value. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 November 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int I, the power of -1. // // Output, double R8_MOP, the I-th power of -1. // { double value; if ( ( i % 2 ) == 0 ) { value = 1.0; } else { value = -1.0; } return value; } //****************************************************************************80 void r8vec_copy ( int n, double a1[], double a2[] ) //****************************************************************************80 // // Purpose: // // R8VEC_COPY copies an R8VEC. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vectors. // // Input, double A1[N], the vector to be copied. // // Output, double A2[N], the copy of A1. // { int i; for ( i = 0; i < n; i++ ) { a2[i] = a1[i]; } return; } //****************************************************************************80 void r8vec_direct_product2 ( int factor_index, int factor_order, double factor_value[], int factor_num, int point_num, double w[] ) //****************************************************************************80 // // Purpose: // // R8VEC_DIRECT_PRODUCT2 creates a direct product of R8VEC's. // // Discussion: // // An R8VEC is a vector of R8's. // // To explain what is going on here, suppose we had to construct // a multidimensional quadrature rule as the product of K rules // for 1D quadrature. // // The product rule will be represented as a list of points and weights. // // The J-th item in the product rule will be associated with // item J1 of 1D rule 1, // item J2 of 1D rule 2, // ..., // item JK of 1D rule K. // // In particular, // X(J) = ( X(1,J1), X(2,J2), ..., X(K,JK)) // and // W(J) = W(1,J1) * W(2,J2) * ... * W(K,JK) // // So we can construct the quadrature rule if we can properly // distribute the information in the 1D quadrature rules. // // This routine carries out that task for the weights W. // // Another way to do this would be to compute, one by one, the // set of all possible indices (J1,J2,...,JK), and then index // the appropriate information. An advantage of the method shown // here is that you can process the K-th set of information and // then discard it. // // Example: // // Rule 1: // Order = 4 // W(1:4) = ( 2, 3, 5, 7 ) // // Rule 2: // Order = 3 // W(1:3) = ( 11, 13, 17 ) // // Rule 3: // Order = 2 // W(1:2) = ( 19, 23 ) // // Product Rule: // Order = 24 // W(1:24) = // ( 2 * 11 * 19 ) // ( 3 * 11 * 19 ) // ( 4 * 11 * 19 ) // ( 7 * 11 * 19 ) // ( 2 * 13 * 19 ) // ( 3 * 13 * 19 ) // ( 5 * 13 * 19 ) // ( 7 * 13 * 19 ) // ( 2 * 17 * 19 ) // ( 3 * 17 * 19 ) // ( 5 * 17 * 19 ) // ( 7 * 17 * 19 ) // ( 2 * 11 * 23 ) // ( 3 * 11 * 23 ) // ( 5 * 11 * 23 ) // ( 7 * 11 * 23 ) // ( 2 * 13 * 23 ) // ( 3 * 13 * 23 ) // ( 5 * 13 * 23 ) // ( 7 * 13 * 23 ) // ( 2 * 17 * 23 ) // ( 3 * 17 * 23 ) // ( 5 * 17 * 23 ) // ( 7 * 17 * 23 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 April 2009 // // Author: // // John Burkardt // // Parameters: // // Input, int FACTOR_INDEX, the index of the factor being processed. // The first factor processed must be factor 0. // // Input, int FACTOR_ORDER, the order of the factor. // // Input, double FACTOR_VALUE[FACTOR_ORDER], the factor values for // factor FACTOR_INDEX. // // Input, int FACTOR_NUM, the number of factors. // // Input, int POINT_NUM, the number of elements in the direct product. // // Input/output, double W[POINT_NUM], the elements of the // direct product, which are built up gradually. // // Local Parameters: // // Local, integer START, the first location of a block of values to set. // // Local, integer CONTIG, the number of consecutive values to set. // // Local, integer SKIP, the distance from the current value of START // to the next location of a block of values to set. // // Local, integer REP, the number of blocks of values to set. // { static int contig = 0; int i; int j; int k; static int rep = 0; static int skip = 0; int start; if ( factor_index == 0 ) { contig = 1; skip = 1; rep = point_num; for ( i = 0; i < point_num; i++ ) { w[i] = 1.0; } } rep = rep / factor_order; skip = skip * factor_order; for ( j = 0; j < factor_order; j++ ) { start = 0 + j * contig; for ( k = 1; k <= rep; k++ ) { for ( i = start; i < start + contig; i++ ) { w[i] = w[i] * factor_value[j]; } start = start + skip; } } contig = contig * factor_order; return; } //***************************************************************************80 void sparse_grid ( int dim_num, int level_max, int rule, int point_num, double grid_weight[], double grid_point[] ) //***************************************************************************80 // // Purpose: // // SPARSE_GRID computes a sparse grid. // // Discussion: // // A Smolyak construction is used to create a multidimensional sparse grid. // // The user specifies: // * the spatial dimension of the quadrature region, // * the level that defines the Smolyak grid. // * the 1D quadrature rule. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 March 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 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. // // Input, int POINT_NUM, the number of points in the grid, // as determined by LEVELS_INDEX_SIZE. // // Output, double GRID_WEIGHT[POINT_NUM], the weights. // // Output, double GRID_POINT[DIM_NUM*POINT_NUM], the points. // { if ( rule == 1 ) { sparse_grid_cfn ( dim_num, level_max, rule, point_num, grid_weight, grid_point ); } else if ( 2 <= rule && rule <= 4 ) { sparse_grid_ofn ( dim_num, level_max, rule, point_num, grid_weight, grid_point ); } else if ( 5 <= rule && rule <= 6 ) { sparse_grid_own ( dim_num, level_max, rule, point_num, grid_weight, grid_point ); } else if ( 7 == rule ) { sparse_grid_onn ( dim_num, level_max, rule, point_num, grid_weight, grid_point ); } else { cout << "\n"; cout << "SPARSE_GRID - Fatal error!\n"; cout << " Illegal input rule index = " << rule << "\n"; exit ( 1 ); } return; } //****************************************************************************80 int sparse_grid_cc_size ( int dim_num, int level_max ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_CC_SIZE sizes a sparse grid using Clenshaw Curtis rules. // // Discussion: // // The grid is defined as the sum of the product rules whose LEVEL // satisfies: // // 0 <= LEVEL <= LEVEL_MAX. // // This calculation is much faster than a previous method. It simply // computes the number of new points that are added at each level in the // 1D rule, and then counts the new points at a given DIM_NUM dimensional // level vector as the product of the new points added in each dimension. // // This approach will work for nested families, and may be extensible // to other families, and to mixed rules. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 December 2009 // // 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 dim; int h; int j; int l; int level; int *level_1d; bool more; int *new_1d; int point_num; int t; int v; // // Special case. // if ( level_max < 0 ) { point_num = 0; return point_num; } if ( level_max == 0 ) { point_num = 1; return point_num; } // // Construct the vector that counts the new points in the 1D rule. // new_1d = new int[level_max+1]; new_1d[0] = 1; new_1d[1] = 2; j = 1; for ( l = 2; l <= level_max; l++ ) { j = j * 2; new_1d[l] = j; } // // Count the number of points by counting the number of new points // associated with each level vector. // level_1d = new int[dim_num]; point_num = 0; for ( level = 0; level <= level_max; level++ ) { more = false; h = 0; t = 0; for ( ; ;) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); v = 1; for ( dim = 0; dim < dim_num; dim++ ) { v = v * new_1d[level_1d[dim]]; } point_num = point_num + v; if ( !more ) { break; } } } delete [] level_1d; delete [] new_1d; return point_num; } //****************************************************************************80 void sparse_grid_cfn ( int dim_num, int level_max, int rule, int point_num, double grid_weight[], double grid_point[] ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_CFN computes a sparse grid based on a CFN 1D rule. // // Discussion: // // The 1D quadrature rule is assumed to be Closed Fully Nested. // // Closed Fully Nested rules include Clenshaw Curtis rules. // // A Smolyak construction is used to create a multidimensional sparse grid. // // The user specifies: // * the spatial dimension of the quadrature region, // * the level that defines the Smolyak grid. // * the quadrature rule. // * the number of points. // // 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, controls the size of the final sparse grid. // // 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. // // Input, int POINT_NUM, the number of points in the grid, as determined // by SPARSE_GRID_SIZE_CFN. // // Output, double GRID_WEIGHTS[POINT_NUM], the weights. // // Output, double GRID_POINTS[DIM_NUM*POINT_NUM], the points. // { int dim; int *grid_base; int *grid_index; int order_max; int point; if ( rule != 1 ) { cout << "\n"; cout << "SPARSE_GRID_CFN - Fatal error!\n"; cout << " Illegal input rule index = " << rule << "\n"; exit ( 1 ); } // // Determine the index vector, relative to the full product grid, // that identifies the points in the sparse grid. // grid_index = new int[dim_num*point_num]; grid_base = new int[dim_num*point_num]; levels_index_cfn ( dim_num, level_max, point_num, grid_index, grid_base ); // // Compute the physical coordinates of the abscissas. // if ( 0 == level_max ) { order_max = 1; } else { order_max = i4_power ( 2, level_max ) + 1; } for ( point = 0; point < point_num; point++ ) { for ( dim = 0; dim < dim_num; dim++ ) { if ( rule == 1 ) { grid_point[dim+point*dim_num] = cc_abscissa ( order_max, grid_index[dim+point*dim_num] + 1 ); } } } // // Gather the weights. // sparse_grid_weights_cfn ( dim_num, level_max, rule, point_num, grid_index, grid_weight ); delete [] grid_base; delete [] grid_index; return; } //***************************************************************************80 void sparse_grid_ofn ( int dim_num, int level_max, int rule, int point_num, double grid_weight[], double grid_point[] ) //***************************************************************************80 // // Purpose: // // SPARSE_GRID_OFN computes a sparse grid based on an OFN 1D rule. // // Discussion: // // The 1D quadrature rule is assumed to be Open Fully Nested. // // Open Fully Nested rules include Fejer 1, Fejer 2, and Gauss Patterson rules. // // A Smolyak construction is used to create a multidimensional sparse grid. // // The user specifies: // * the spatial dimension of the quadrature region, // * the level that defines the Smolyak grid. // * the 1D quadrature rule. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 March 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 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. // // Input, int POINT_NUM, the number of points in the grid, // as determined by LEVELS_INDEX_SIZE. // // Output, double GRID_WEIGHT[POINT_NUM], the weights. // // Output, double GRID_POINT[DIM_NUM*POINT_NUM], the points. // { int dim; int *grid_base; int *grid_index; int order_max; int point; if ( rule < 2 || 4 < rule ) { cout << "\n"; cout << "SPARSE_GRID_OFN - Fatal error!\n"; cout << " Illegal input rule index = " << rule << "\n"; exit ( 1 ); } // // Determine the index vector, relative to the full product grid, // that identifies the points in the sparse grid. // grid_base = new int[dim_num*point_num]; grid_index = new int[dim_num*point_num]; levels_index_ofn ( dim_num, level_max, point_num, grid_index, grid_base ); // // Compute the physical coordinates of the abscissas. // order_max = i4_power ( 2, level_max + 1 ) - 1; for ( point = 0; point < point_num; point++ ) { for ( dim = 0; dim < dim_num; dim++ ) { if ( rule == 2 ) { grid_point[dim+point*dim_num] = f1_abscissa ( order_max, grid_index[dim+point*dim_num] ); } else if ( rule == 3 ) { grid_point[dim+point*dim_num] = f2_abscissa ( order_max, grid_index[dim+point*dim_num] ); } else if ( rule == 4 ) { grid_point[dim+point*dim_num] = gp_abscissa ( order_max, grid_index[dim+point*dim_num] ); } } } // // Gather the weights. // sparse_grid_weights_ofn ( dim_num, level_max, rule, point_num, grid_index, grid_weight ); delete [] grid_base; delete [] grid_index; return; } //****************************************************************************80 int sparse_grid_ofn_size ( int dim_num, int level_max ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_OFN_SIZE sizes a sparse grid using Open Fully Nested rules. // // Discussion: // // The grid is defined as the sum of the product rules whose LEVEL // satisfies: // // 0 <= LEVEL <= LEVEL_MAX. // // This calculation is much faster than a previous method. It simply // computes the number of new points that are added at each level in the // 1D rule, and then counts the new points at a given DIM_NUM dimensional // level vector as the product of the new points added in each dimension. // // This approach will work for nested families, and may be extensible // to other families, and to mixed rules. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 December 2009 // // 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 dim; int h; int j; int l; int level; int *level_1d; bool more; int *new_1d; int point_num; int t; int v; // // Special case. // if ( level_max < 0 ) { point_num = 0; return point_num; } if ( level_max == 0 ) { point_num = 1; return point_num; } // // Construct the vector that counts the new points in the 1D rule. // new_1d = new int[level_max+1]; new_1d[0] = 1; for ( l = 1; l <= level_max; l++ ) { new_1d[l] = 2 * new_1d[l-1]; } // // Count the number of points by counting the number of new points // associated with each level vector. // level_1d = new int[dim_num]; point_num = 0; for ( level = 0; level <= level_max; level++ ) { more = false; h = 0; t = 0; for ( ; ;) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); v = 1; for ( dim = 0; dim < dim_num; dim++ ) { v = v * new_1d[level_1d[dim]]; } point_num = point_num + v; if ( !more ) { break; } } } delete [] level_1d; delete [] new_1d; return point_num; } //****************************************************************************80 void sparse_grid_onn ( int dim_num, int level_max, int rule, int point_num, double grid_weight[], double grid_point[] ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_ONN computes a sparse grid based on a ONN 1D rule. // // Discussion: // // The 1D quadrature rule is assumed to be Open Non-Nested. // Such rules include Gauss Laguerre rules. // // A Smolyak construction is used to create a multidimensional sparse grid. // // The user specifies: // * the spatial dimension of the quadrature region, // * the level that defines the Smolyak grid. // * the quadrature rule; // * the number of points in the rule. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 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. // // Input, int POINT_NUM, the number of points in the grid, as determined // by SPARSE_GRID_SIZE_ONN. // // Output, double GRID_WEIGHT[POINT_NUM], the weights. // // Output, double GRID_POINT[DIM_NUM*POINT_NUM], the points. // { double coeff; int dim; int *grid_base2; int *grid_index2; double *grid_weight2; int h; int level; int *level_1d; int level_min; bool more; int *order_1d; int order_nd; int order_max; int point; int point_num2; int t; for ( point = 0; point < point_num; point++ ) { grid_weight[point] = 0.0; } // // The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. // point_num2 = 0; level_min = i4_max ( 0, level_max + 1 - dim_num ); grid_base2 = new int[dim_num]; level_1d = new int[dim_num]; 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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // The relationship is the same as for other OPEN rules. // level_to_order_open ( dim_num, level_1d, order_1d ); 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. // order_nd = i4vec_product ( dim_num, order_1d ); // // Compute the weights for this product grid. // grid_weight2 = product_weights ( dim_num, order_1d, order_nd, rule ); // // Now determine the coefficient of the weight. // coeff = r8_mop ( level_max - level ) * r8_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). // grid_index2 = multigrid_index_onn ( dim_num, order_1d, order_nd ); for ( point = 0; point < order_nd; point++ ) { if ( point_num <= point_num2 ) { cout << "\n"; cout << "SPARSE_GRID_ONN - Fatal error!\n"; cout << " Exceeding maximum point index POINT_NUM = " << point_num << "\n"; exit ( 1 ); } lg_abscissa ( dim_num, 1, grid_index2+point*dim_num, grid_base2, grid_point+point_num2*dim_num ); grid_weight[point_num2] = coeff * grid_weight2[point]; point_num2 = point_num2 + 1; } delete [] grid_index2; delete [] grid_weight2; if ( !more ) { break; } } } delete [] grid_base2; delete [] level_1d; delete [] order_1d; if ( point_num2 < point_num ) { cout << "\n"; cout << "SPARSE_GRID_ONN - Fatal error!\n"; cout << " Set fewer points than POINT_NUM = " << point_num << "\n"; exit ( 1 ); } return; } //****************************************************************************80 void sparse_grid_own ( int dim_num, int level_max, int rule, int point_num, double grid_weight[], double grid_point[] ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_OWN computes a sparse grid based on an OWN 1D rule. // // Discussion: // // The 1D quadrature rule is assumed to be Open Weakly Nested. // Such rules include Gauss Hermite and Gauss Legendre rules. // // A Smolyak construction is used to create a multidimensional sparse grid. // // The user specifies: // * the spatial dimension of the quadrature region, // * the level that defines the Smolyak grid, // * the rule; // * the number of points. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 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. // // Input, int POINT_NUM, the number of points in the grid, as determined // by LEVELS_INDEX_SIZE_OWN. // // Output, double GRID_WEIGHT[POINT_NUM], the weights. // // Output, double GRID_POINT[DIM_NUM*POINT_NUM], the points. // { double coeff; int dim; int *grid_base2; int *grid_index2; int *grid_level; double *grid_point_temp; double *grid_weight2; int h; int level; int *level_1d; int level_min; int level_min2; bool more; int *order_1d; int order_nd; int order_max; int point; int point_num2; int point2; int point3; int t; for ( point = 0; point < point_num; point++ ) { grid_weight[point] = 0.0; } // // The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. // point_num2 = 0; level_min = i4_max ( 0, level_max + 1 - dim_num ); if ( dim_num == 1 ) { level_min2 = level_min; } else { level_min2 = 0; } grid_base2 = new int[dim_num]; level_1d = new int[dim_num]; order_1d = new int[dim_num]; for ( level = level_min2; level <= level_max; level++ ) { // // The middle loop generates the next partition LEVEL_1D(1:DIM_NUM) // that adds up to LEVEL. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &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. // level_to_order_open ( dim_num, level_1d, order_1d ); 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. // order_nd = i4vec_product ( dim_num, order_1d ); // // Compute the weights for this product grid. // grid_weight2 = product_weights ( dim_num, order_1d, order_nd, rule ); // // Now determine the coefficient of the weight. // coeff = r8_mop ( level_max - level ) * r8_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). // grid_index2 = multigrid_index_own ( 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. // grid_level = index_level_own ( 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 ) { if ( point_num <= point_num2 ) { cout << "\n"; cout << "SPARSE_GRID_OWN - Fatal error!\n"; cout << " Exceeding maximum point index POINT_NUM = " << point_num << "\n"; exit ( 1 ); } if ( rule == 5 ) { gl_abscissa ( dim_num, 1, grid_index2+point*dim_num, grid_base2, grid_point+point_num2*dim_num ); } else if ( rule == 6 ) { gh_abscissa ( dim_num, 1, grid_index2+point*dim_num, grid_base2, grid_point+point_num2*dim_num ); } else { cout << "\n"; cout << "SPARSE_GRID_OWN - Fatal error!\n"; cout << " Unrecognized rule number = " << rule << "\n"; exit ( 1 ); } if ( level_min <= level ) { grid_weight[point_num2] = coeff * grid_weight2[point]; } point_num2 = point_num2 + 1; } // // or an already existing point (create point temporarily, find match, // add weight to matched point's weight). // else { if ( level_min <= level ) { grid_point_temp = new double[dim_num]; if ( rule == 5 ) { gl_abscissa ( dim_num, 1, grid_index2+point*dim_num, grid_base2, grid_point_temp ); } else if ( rule == 6 ) { gh_abscissa ( dim_num, 1, grid_index2+point*dim_num, grid_base2, grid_point_temp ); } else { cout << "\n"; cout << "SPARSE_GRID_OWN - Fatal error!\n"; cout << " Unrecognized rule number = " << rule << "\n"; exit ( 1 ); } for ( point2 = 0; point2 < point_num2; point2++ ) { point3 = point2; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_point[dim+point2*dim_num] != grid_point_temp[dim] ) { point3 = -1; break; } } if ( point3 == point2 ) { break; } } if ( point3 == -1 ) { cout << "\n"; cout << "SPARSE_GRID_OWN - Fatal error!\n"; cout << " Could not match point.\n"; exit ( 1 ); } grid_weight[point3] = grid_weight[point3] + ( double ) ( coeff ) * grid_weight2[point]; } } } delete [] grid_index2; delete [] grid_level; delete [] grid_weight2; if ( !more ) { break; } } } delete [] grid_base2; delete [] level_1d; delete [] order_1d; if ( point_num2 < point_num ) { cout << "\n"; cout << "SPARSE_GRID_OWN - Fatal error!\n"; cout << " Set fewer points than POINT_NUM = " << point_num << "\n"; exit ( 1 ); } return; } //****************************************************************************80 void sparse_grid_weights_cfn ( int dim_num, int level_max, int rule, int point_num, int grid_index[], double grid_weight[] ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_WEIGHTS_CFN computes sparse grid weights based on a CFN 1D rule. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 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. // // 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. // { bool all_equal; double coeff; int dim; int *grid_index2; double *grid_weight2; int h; int level; int *level_1d; int level_min; bool more; int order_nd; int *order_1d; int point; int point2; int t; if ( level_max == 0 ) { for ( point = 0; point < point_num; point++ ) { grid_weight[point] = i4_power ( 2, dim_num ); } return; } level_1d = new int[dim_num]; order_1d = new int[dim_num]; for ( point = 0; point < point_num; point++ ) { grid_weight[point] = 0.0; } level_min = i4_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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_closed ( dim_num, level_1d, order_1d ); // // The product of the 1D orders gives us the number of points in this grid. // order_nd = i4vec_product ( dim_num, order_1d ); // // Generate the indices of the points corresponding to the grid. // grid_index2 = multigrid_index_cfn ( dim_num, order_1d, order_nd ); // // Compute the weights for this grid. // grid_weight2 = product_weights ( dim_num, order_1d, order_nd, rule ); // // Adjust the grid indices to reflect LEVEL_MAX. // multigrid_scale_closed ( dim_num, order_nd, level_max, level_1d, grid_index2 ); // // Now determine the coefficient. // coeff = r8_mop ( level_max - level ) * r8_choose ( dim_num - 1, level_max - level ); for ( point2 = 0; point2 < order_nd; point2++ ) { for ( point = 0; point < point_num; point++ ) { all_equal = true; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_index2[dim+point2*dim_num] != grid_index[dim+point*dim_num] ) { all_equal = false; break; } } if ( all_equal ) { grid_weight[point] = grid_weight[point] + coeff * grid_weight2[point2]; break; } } } delete [] grid_index2; delete [] grid_weight2; if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; return; } //****************************************************************************80 void sparse_grid_weights_ofn ( int dim_num, int level_max, int rule, int point_num, int grid_index[], double grid_weight[] ) //****************************************************************************80 // // Purpose: // // SPARSE_GRID_WEIGHTS_OFN computes sparse grid weights based on a OFN 1D rule. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 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 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. // // 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. // { bool all_equal; double coeff; int dim; int *grid_index2; double *grid_weight2; int h; int level; int *level_1d; int level_min; bool more; int order_nd; int *order_1d; int point; int point2; int t; if ( level_max == 0 ) { for ( point = 0; point < point_num; point++ ) { grid_weight[point] = i4_power ( 2, dim_num ); } return; } level_1d = new int[dim_num]; order_1d = new int[dim_num]; for ( point = 0; point < point_num; point++ ) { grid_weight[point] = 0.0; } level_min = i4_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. // more = false; h = 0; t = 0; for ( ; ; ) { comp_next ( level, dim_num, level_1d, &more, &h, &t ); // // Transform each 1D level to a corresponding 1D order. // level_to_order_open ( dim_num, level_1d, order_1d ); // // The product of the 1D orders gives us the number of points in this grid. // order_nd = i4vec_product ( dim_num, order_1d ); // // Generate the indices of the points corresponding to the grid. // grid_index2 = multigrid_index_ofn ( dim_num, order_1d, order_nd ); // // Compute the weights for this grid. // grid_weight2 = product_weights ( dim_num, order_1d, order_nd, rule ); // // Adjust the grid indices to reflect LEVEL_MAX. // multigrid_scale_open ( dim_num, order_nd, level_max, level_1d, grid_index2 ); // // Now determine the coefficient. // coeff = r8_mop ( level_max - level ) * r8_choose ( dim_num - 1, level_max - level ); for ( point2 = 0; point2 < order_nd; point2++ ) { for ( point = 0; point < point_num; point++ ) { all_equal = true; for ( dim = 0; dim < dim_num; dim++ ) { if ( grid_index2[dim+point2*dim_num] != grid_index[dim+point*dim_num] ) { all_equal = false; break; } } if ( all_equal ) { grid_weight[point] = grid_weight[point] + coeff * grid_weight2[point2]; break; } } } delete [] grid_index2; delete [] grid_weight2; if ( !more ) { break; } } } delete [] level_1d; delete [] order_1d; return; } //****************************************************************************80 void timestamp ( ) //****************************************************************************80 // // Purpose: // // TIMESTAMP prints the current YMDHMS date as a time stamp. // // Example: // // 31 May 2001 09:45:54 AM // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 July 2009 // // Author: // // John Burkardt // // Parameters: // // None // { # define TIME_SIZE 40 static char time_buffer[TIME_SIZE]; const struct std::tm *tm_ptr; size_t len; std::time_t now; now = std::time ( NULL ); tm_ptr = std::localtime ( &now ); len = std::strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm_ptr ); std::cout << time_buffer << "\n"; return; # undef TIME_SIZE } //****************************************************************************80 void vec_colex_next2 ( int dim_num, int base[], int a[], bool *more ) //****************************************************************************80 // // Purpose: // // VEC_COLEX_NEXT2 generates vectors in colex order. // // Discussion: // // The vectors are produced in colexical order, starting with // // (0, 0, ...,0), // (1, 0, ...,0), // ... // (BASE(1)-1,0, ...,0) // // (0, 1, ...,0) // (1, 1, ...,0) // ... // (BASE(1)-1,1, ...,0) // // (0, 2, ...,0) // (1, 2, ...,0) // ... // (BASE(1)-1,BASE(2)-1,...,BASE(DIM_NUM)-1). // // Example: // // DIM_NUM = 2, // BASE = { 3, 3 } // // 0 0 // 1 0 // 2 0 // 0 1 // 1 1 // 2 1 // 0 2 // 1 2 // 2 2 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 May 2007 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the spatial dimension. // // Input, int BASE[DIM_NUM], the bases to be used in each dimension. // In dimension I, entries will range from 0 to BASE[I]-1. // // Output, int A[DIM_NUM], the next vector. // // Input/output, bool *MORE. Set this variable false before // the first call. On return, MORE is TRUE if another vector has // been computed. If MORE is returned FALSE, ignore the output // vector and stop calling the routine. // { int i; if ( !( *more ) ) { for ( i = 0; i < dim_num; i++ ) { a[i] = 0; } *more = true; } else { for ( i = 0; i < dim_num; i++ ) { a[i] = a[i] + 1; if ( a[i] < base[i] ) { return; } a[i] = 0; } *more = false; } return; }