function sparse_grid_gl_dataset ( dim_num, level_max ) %*****************************************************************************80 % %% SPARSE_GRID_GL_DATASET is the main program. % % Discussion: % % This program computes a sparse grid quadrature rule based on a 1D % Gauss-Legendre rule and writes it to a file.. % % The user specifies: % * the spatial dimension of the quadrature region, % * the level that defines the Smolyak grid. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 08 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. % timestamp ( ); fprintf ( 1, '\n' ); fprintf ( 1, 'SPARSE_GRID_GL_DATASET\n' ); fprintf ( 1, ' MATLAB version\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' Compute the abscissas and weights of a quadrature rule\n' ); fprintf ( 1, ' associated with a sparse grid derived from a Smolyak\n' ); fprintf ( 1, ' construction based on 1D Gauss-Legendre rules.\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' Inputs to the program include:\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' DIM_NUM, the spatial dimension.\n' ); fprintf ( 1, ' (typically in the range of 2 to 10)\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' LEVEL_MAX, the "level" of the sparse grid.\n' ); fprintf ( 1, ' (typically in the range of 0, 1, 2, 3, ...\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' Output from the program includes:\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' A printed table of the abscissas and weights.\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' * A set of 3 files that define the quadrature rule.\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' "gl_d?_level?_r.txt", a file of the ranges.\n' ); fprintf ( 1, ' "gl_d?_level?_w.txt", a file of the weights;\n' ); fprintf ( 1, ' "gl_d?_level?_x.txt", a file of the abscissas;\n' ); % % Get the spatial dimension. % if ( nargin < 1) fprintf ( 1, '\n' ); dim_num = input ( ' Enter the value of DIM_NUM (1 or greater): ' ); elseif ( ischar ( dim_num ) ) dim_num = str2num ( dim_num ); end fprintf ( 1, '\n' ); fprintf ( 1, ' Spatial dimension requested is = %d\n', dim_num ); % % Get the level. % if ( nargin < 2 ) fprintf ( 1, '\n' ); level_max = input ( ' Enter the value of LEVEL_MAX (0 or greater): ' ); elseif ( ischar ( level_max ) ) level_max = str2num ( level_max ); end level_min = max ( 0, level_max + 1 - dim_num ); fprintf ( 1, '\n' ); fprintf ( 1, ' LEVEL_MIN = %d\n', level_min ); fprintf ( 1, ' LEVEL_MAX = %d\n', level_max ); % % How many distinct points will there be? % point_num = sparse_grid_gl_size ( dim_num, level_max ); fprintf ( 1, '\n' ); fprintf ( 1, ' The number of distinct abscissas in the\n' ); fprintf ( 1, ' quadrature rule is determined from the spatial\n' ); fprintf ( 1, ' dimension DIM_NUM and the level LEVEL_MAX.\n' ); fprintf ( 1, ' For the given input, this value will be = %d\n', point_num ); r = zeros ( dim_num, 2 ); % % Compute the weights and points. % r(1:dim_num,1) = -1.0; r(1:dim_num,2) = +1.0; [ w, x ] = sparse_grid_gl ( dim_num, level_max, point_num ); r8mat_transpose_print_some ( dim_num, point_num, x, 1, 1, ... dim_num, 10, ' First 10 grid points:' ); r8vec_print_some ( point_num, w, 1, 10, ' First 10 weights:' ); weight_sum = sum ( w(1:point_num) ); fprintf ( 1, '\n' ); fprintf ( 1, ' Weights sum to %24.16f\n', weight_sum ); fprintf ( 1, ' Correct value is %24.16f\n', 2.0^dim_num ); % % Write the rule to files. % r_filename = sprintf ( 'gl_d%d_level%d_r.txt', dim_num, level_max ); w_filename = sprintf ( 'gl_d%d_level%d_w.txt', dim_num, level_max ); x_filename = sprintf ( 'gl_d%d_level%d_x.txt', dim_num, level_max ); fprintf ( 1, '\n' ); fprintf ( 1, ' Creating R file = "%s".\n', r_filename ); r8mat_write ( r_filename, dim_num, 2, r ); fprintf ( 1, ' Creating W file = "%s".\n', w_filename ); r8mat_write ( w_filename, 1, point_num, w ); fprintf ( 1, ' Creating X file = "%s".\n', x_filename ); r8mat_write ( x_filename, dim_num, point_num, x ); % % Terminate. % fprintf ( 1, '\n' ); fprintf ( 1, 'SPARSE)GRID_GL_DATASET:\n' ); fprintf ( 1, ' Normal end of execution.\n' ); fprintf ( 1, '\n' ); timestamp ( ); return end function [ a, more, h, t ] = comp_next ( n, k, a, more, h, t ) %*****************************************************************************80 % %% 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 and Herbert Wilf % MATLAB 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, integer N, the integer whose compositions are desired. % % Input, integer K, the number of parts in the composition. % % Input, integer A(K), the previous composition. On the first call, % with MORE = FALSE, set A = []. Thereafter, A should be the % value of A output from the previous call. % % Input, logical MORE. The input value of MORE on the first % call should be FALSE, which tells the program to initialize. % On subsequent calls, MORE should be TRUE, or simply the % output value of MORE from the previous call. % % Input, integer H, T, two internal parameters needed for the % computation. The user may need to initialize these before the % very first call, but these initial values are not important. % The user should not alter these parameters once the computation % begins. % % Output, integer A(K), the next composition. % % Output, logical MORE, will be TRUE unless the composition % that is being returned is the final one in the sequence. % % Output, integer H, T, the updated values of the two internal % parameters. % if ( ~more ) t = n; h = 0; a(1) = n; a(2:k) = 0; else if ( 1 < t ) h = 0; end h = h + 1; t = a(h); a(h) = 0; a(1) = t - 1; a(h+1) = a(h+1) + 1; end more = ( a(k) ~= n ); return end function grid_point = gl_abscissa ( dim_num, point_num, grid_index, grid_base ) %*****************************************************************************80 % %% 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 and 127, in order. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 02 October 2007 % % Author: % % John Burkardt % % Parameters: % % Input, integer DIM_NUM, the spatial dimension. % % Input, integer POINT_NUM, the number of points. % % Input, integer GRID_INDEX(DIM_NUM,POINT_NUM), for each % point and dimension, the index of the Gauss-Legendre abscissa. % % Input, integer GRID_BASE(DIM_NUM), the order of the % Gauss-Legendre rule being used in each dimension. % % Output, real GRID_POINT(DIM_NUM), the grid points of % Gauss-Legendre abscissas. % skip = [ 0, 1, 4, 11, 26, 57, 120, 247 ]; x = [ ... 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, ... -0.99982213041530614629963254927125E+00, ... -0.99906293435531189513828920479421E+00, ... -0.99769756618980462107441703193392E+00, ... -0.99572655135202722663543337085008E+00, ... -0.99315104925451714736113079489080E+00, ... -0.98997261459148415760778669967548E+00, ... -0.98619317401693166671043833175407E+00, ... -0.98181502080381411003346312451200E+00, ... -0.97684081234307032681744391886221E+00, ... -0.97127356816152919228894689830512E+00, ... -0.96511666794529212109082507703391E+00, ... -0.95837384942523877114910286998060E+00, ... -0.95104920607788031054790764659636E+00, ... -0.94314718462481482734544963026201E+00, ... -0.93467258232473796857363487794906E+00, ... -0.92563054405623384912746466814259E+00, ... -0.91602655919146580931308861741716E+00, ... -0.90586645826182138280246131760282E+00, ... -0.89515640941708370896904382642451E+00, ... -0.88390291468002656994525794802849E+00, ... -0.87211280599856071141963753428864E+00, ... -0.85979324109774080981203134414483E+00, ... -0.84695169913409759845333931085437E+00, ... -0.83359597615489951437955716480123E+00, ... -0.81973418036507867415511910167470E+00, ... -0.80537472720468021466656079404644E+00, ... -0.79052633423981379994544995252740E+00, ... -0.77519801587020238244496276354566E+00, ... -0.75939907785653667155666366659810E+00, ... -0.74313911167095451292056688997595E+00, ... -0.72642798867407268553569290153270E+00, ... -0.70927585412210456099944463906757E+00, ... -0.69169312100770067015644143286666E+00, ... -0.67369046373825048534668253831602E+00, ... -0.65527881165548263027676505156852E+00, ... -0.63646934240029724134760815684175E+00, ... -0.61727347512685828385763916340822E+00, ... -0.59770286357006522938441201887478E+00, ... -0.57776938897061258000325165713764E+00, ... -0.55748515286193223292186190687872E+00, ... -0.53686246972339756745816636353452E+00, ... -0.51591385950424935727727729906662E+00, ... -0.49465204002278211739494017368636E+00, ... -0.47308991924540524164509989939699E+00, ... -0.45124058745026622733189858020729E+00, ... -0.42911730928019337626254405355418E+00, ... -0.40673351568978256340867288124339E+00, ... -0.38410279579151693577907781452239E+00, ... -0.36123888860586970607092484346723E+00, ... -0.33815567472039850137600027657095E+00, ... -0.31486716786289498148601475374890E+00, ... -0.29138750639370562079451875284568E+00, ... -0.26773094472238862088834352027938E+00, ... -0.24391184465391785797071324453138E+00, ... -0.21994466666968754245452337866940E+00, ... -0.19584396114861085150428162519610E+00, ... -0.17162435953364216500834492248954E+00, ... -0.14730056544908566938932929319807E+00, ... -0.12288734577408297172603365288567E+00, ... -0.98399521677698970751091751509101E-01, ... -0.73851959621048545273440409360569E-01, ... -0.49259562331926630315379321821927E-01, ... -0.24637259757420944614897071846088E-01, ... 0.00000000000000000000000000000000E+00, ... 0.24637259757420944614897071846088E-01, ... 0.49259562331926630315379321821927E-01, ... 0.73851959621048545273440409360569E-01, ... 0.98399521677698970751091751509101E-01, ... 0.12288734577408297172603365288567E+00, ... 0.14730056544908566938932929319807E+00, ... 0.17162435953364216500834492248954E+00, ... 0.19584396114861085150428162519610E+00, ... 0.21994466666968754245452337866940E+00, ... 0.24391184465391785797071324453138E+00, ... 0.26773094472238862088834352027938E+00, ... 0.29138750639370562079451875284568E+00, ... 0.31486716786289498148601475374890E+00, ... 0.33815567472039850137600027657095E+00, ... 0.36123888860586970607092484346723E+00, ... 0.38410279579151693577907781452239E+00, ... 0.40673351568978256340867288124339E+00, ... 0.42911730928019337626254405355418E+00, ... 0.45124058745026622733189858020729E+00, ... 0.47308991924540524164509989939699E+00, ... 0.49465204002278211739494017368636E+00, ... 0.51591385950424935727727729906662E+00, ... 0.53686246972339756745816636353452E+00, ... 0.55748515286193223292186190687872E+00, ... 0.57776938897061258000325165713764E+00, ... 0.59770286357006522938441201887478E+00, ... 0.61727347512685828385763916340822E+00, ... 0.63646934240029724134760815684175E+00, ... 0.65527881165548263027676505156852E+00, ... 0.67369046373825048534668253831602E+00, ... 0.69169312100770067015644143286666E+00, ... 0.70927585412210456099944463906757E+00, ... 0.72642798867407268553569290153270E+00, ... 0.74313911167095451292056688997595E+00, ... 0.75939907785653667155666366659810E+00, ... 0.77519801587020238244496276354566E+00, ... 0.79052633423981379994544995252740E+00, ... 0.80537472720468021466656079404644E+00, ... 0.81973418036507867415511910167470E+00, ... 0.83359597615489951437955716480123E+00, ... 0.84695169913409759845333931085437E+00, ... 0.85979324109774080981203134414483E+00, ... 0.87211280599856071141963753428864E+00, ... 0.88390291468002656994525794802849E+00, ... 0.89515640941708370896904382642451E+00, ... 0.90586645826182138280246131760282E+00, ... 0.91602655919146580931308861741716E+00, ... 0.92563054405623384912746466814259E+00, ... 0.93467258232473796857363487794906E+00, ... 0.94314718462481482734544963026201E+00, ... 0.95104920607788031054790764659636E+00, ... 0.95837384942523877114910286998060E+00, ... 0.96511666794529212109082507703391E+00, ... 0.97127356816152919228894689830512E+00, ... 0.97684081234307032681744391886221E+00, ... 0.98181502080381411003346312451200E+00, ... 0.98619317401693166671043833175407E+00, ... 0.98997261459148415760778669967548E+00, ... 0.99315104925451714736113079489080E+00, ... 0.99572655135202722663543337085008E+00, ... 0.99769756618980462107441703193392E+00, ... 0.99906293435531189513828920479421E+00, ... 0.99982213041530614629963254927125E+00 ... ]; if ( any ( grid_base(1:dim_num) < 0 ) ) fprintf ( 1, '\n' ); fprintf ( 1, 'GL_ABSCISSA - Fatal error!\n' ); fprintf ( 1, ' Some base values are less than 0.\n' ); error ( 'GL_ABSCISSA - Fatal error!' ); end if ( any ( 63 < grid_base(1:dim_num) ) ) fprintf ( 1, '\n' ); fprintf ( 1, 'GL_ABSCISSA - Fatal error!\n' ); fprintf ( 1, ' Some base values are greater than 63.\n' ); error ( 'GL_ABSCISSA - Fatal error!' ); end for point = 1 : point_num for dim = 1 : dim_num level = i4_log_2 ( grid_base(dim) + 1 ); pointer = skip(level+1) + ( grid_index(dim,point) + grid_base(dim) + 1 ); grid_point(dim,point) = x(pointer); end end return end function weight = gl_weights ( order ) %*****************************************************************************80 % %% GL_WEIGHTS returns weights for certain Gauss-Legendre quadrature rules. % % Discussion: % % The allowed orders are 1, 3, 7, 15, 31, 63 or 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, integer ORDER, the order of the rule. % ORDER must be 1, 3, 7, 15, 31, 63, or 127. % % Output, real WEIGHT(ORDER), the weights. % The weights are positive, symmetric and should sum to 2. % if ( order == 1 ) weight(1) = 2.0E+00; elseif ( order == 3 ) weight(1) = 0.555555555555555555555555555555E+00; weight(2) = 0.888888888888888888888888888888E+00; weight(3) = 0.555555555555555555555555555555E+00; elseif ( order == 7 ) weight(1) = 0.129484966168869693270611432679E+00; weight(2) = 0.279705391489276667901467771424E+00; weight(3) = 0.381830050505118944950369775489E+00; weight(4) = 0.417959183673469387755102040816E+00; weight(5) = 0.381830050505118944950369775489E+00; weight(6) = 0.279705391489276667901467771424E+00; weight(7) = 0.129484966168869693270611432679E+00; elseif ( order == 15 ) weight(1) = 0.307532419961172683546283935772E-01; weight(2) = 0.703660474881081247092674164507E-01; weight(3) = 0.107159220467171935011869546686E+00; weight(4) = 0.139570677926154314447804794511E+00; weight(5) = 0.166269205816993933553200860481E+00; weight(6) = 0.186161000015562211026800561866E+00; weight(7) = 0.198431485327111576456118326444E+00; weight(8) = 0.202578241925561272880620199968E+00; weight(9) = 0.198431485327111576456118326444E+00; weight(10) = 0.186161000015562211026800561866E+00; weight(11) = 0.166269205816993933553200860481E+00; weight(12) = 0.139570677926154314447804794511E+00; weight(13) = 0.107159220467171935011869546686E+00; weight(14) = 0.703660474881081247092674164507E-01; weight(15) = 0.307532419961172683546283935772E-01; elseif ( order == 31 ) weight( 1) = 0.74708315792487746093913218970494E-02; weight( 2) = 0.17318620790310582463552990782414E-01; weight( 3) = 0.27009019184979421800608642617676E-01; weight( 4) = 0.36432273912385464024392008749009E-01; weight( 5) = 0.45493707527201102902315857856518E-01; weight( 6) = 0.54103082424916853711666259085477E-01; weight( 7) = 0.62174786561028426910343543686657E-01; weight( 8) = 0.69628583235410366167756126255124E-01; weight( 9) = 0.76390386598776616426357674901331E-01; weight(10) = 0.82392991761589263903823367431962E-01; weight(11) = 0.87576740608477876126198069695333E-01; weight(12) = 0.91890113893641478215362871607150E-01; weight(13) = 0.95290242912319512807204197487597E-01; weight(14) = 0.97743335386328725093474010978997E-01; weight(15) = 0.99225011226672307874875514428615E-01; weight(16) = 0.99720544793426451427533833734349E-01; weight(17) = 0.99225011226672307874875514428615E-01; weight(18) = 0.97743335386328725093474010978997E-01; weight(19) = 0.95290242912319512807204197487597E-01; weight(20) = 0.91890113893641478215362871607150E-01; weight(21) = 0.87576740608477876126198069695333E-01; weight(22) = 0.82392991761589263903823367431962E-01; weight(23) = 0.76390386598776616426357674901331E-01; weight(24) = 0.69628583235410366167756126255124E-01; weight(25) = 0.62174786561028426910343543686657E-01; weight(26) = 0.54103082424916853711666259085477E-01; weight(27) = 0.45493707527201102902315857856518E-01; weight(28) = 0.36432273912385464024392008749009E-01; weight(29) = 0.27009019184979421800608642617676E-01; weight(30) = 0.17318620790310582463552990782414E-01; weight(31) = 0.74708315792487746093913218970494E-02; elseif ( order == 63 ) weight( 1) = 0.18398745955770837880499331680577E-02; weight( 2) = 0.42785083468637618661951422543371E-02; weight( 3) = 0.67102917659601362519069109850892E-02; weight( 4) = 0.91259686763266563540586445877022E-02; weight( 5) = 0.11519376076880041750750606118707E-01; weight( 6) = 0.13884612616115610824866086365937E-01; weight( 7) = 0.16215878410338338882283672974995E-01; weight( 8) = 0.18507464460161270409260545805144E-01; weight( 9) = 0.20753761258039090775341953421471E-01; weight(10) = 0.22949271004889933148942319561770E-01; weight(11) = 0.25088620553344986618630138068443E-01; weight(12) = 0.27166574359097933225189839439413E-01; weight(13) = 0.29178047208280526945551502154029E-01; weight(14) = 0.31118116622219817508215988557189E-01; weight(15) = 0.32982034883779341765683179672459E-01; weight(16) = 0.34765240645355877697180504642788E-01; weight(17) = 0.36463370085457289630452409787542E-01; weight(18) = 0.38072267584349556763638324927889E-01; weight(19) = 0.39587995891544093984807928149202E-01; weight(20) = 0.41006845759666398635110037009072E-01; weight(21) = 0.42325345020815822982505485403028E-01; weight(22) = 0.43540267083027590798964315704401E-01; weight(23) = 0.44648638825941395370332669516813E-01; weight(24) = 0.45647747876292608685885992608542E-01; weight(25) = 0.46535149245383696510395418746953E-01; weight(26) = 0.47308671312268919080604988338844E-01; weight(27) = 0.47966421137995131411052756195132E-01; weight(28) = 0.48506789097883847864090099145802E-01; weight(29) = 0.48928452820511989944709361549215E-01; weight(30) = 0.49230380423747560785043116988145E-01; weight(31) = 0.49411833039918178967039646116705E-01; weight(32) = 0.49472366623931020888669360420926E-01; weight(33) = 0.49411833039918178967039646116705E-01; weight(34) = 0.49230380423747560785043116988145E-01; weight(35) = 0.48928452820511989944709361549215E-01; weight(36) = 0.48506789097883847864090099145802E-01; weight(37) = 0.47966421137995131411052756195132E-01; weight(38) = 0.47308671312268919080604988338844E-01; weight(39) = 0.46535149245383696510395418746953E-01; weight(40) = 0.45647747876292608685885992608542E-01; weight(41) = 0.44648638825941395370332669516813E-01; weight(42) = 0.43540267083027590798964315704401E-01; weight(43) = 0.42325345020815822982505485403028E-01; weight(44) = 0.41006845759666398635110037009072E-01; weight(45) = 0.39587995891544093984807928149202E-01; weight(46) = 0.38072267584349556763638324927889E-01; weight(47) = 0.36463370085457289630452409787542E-01; weight(48) = 0.34765240645355877697180504642788E-01; weight(49) = 0.32982034883779341765683179672459E-01; weight(50) = 0.31118116622219817508215988557189E-01; weight(51) = 0.29178047208280526945551502154029E-01; weight(52) = 0.27166574359097933225189839439413E-01; weight(53) = 0.25088620553344986618630138068443E-01; weight(54) = 0.22949271004889933148942319561770E-01; weight(55) = 0.20753761258039090775341953421471E-01; weight(56) = 0.18507464460161270409260545805144E-01; weight(57) = 0.16215878410338338882283672974995E-01; weight(58) = 0.13884612616115610824866086365937E-01; weight(59) = 0.11519376076880041750750606118707E-01; weight(60) = 0.91259686763266563540586445877022E-02; weight(61) = 0.67102917659601362519069109850892E-02; weight(62) = 0.42785083468637618661951422543371E-02; weight(63) = 0.18398745955770837880499331680577E-02; elseif ( order == 127 ) weight( 1) = 0.45645726109586654495731936146574E-03; weight( 2) = 0.10622766869538486959954760554099E-02; weight( 3) = 0.16683488125171936761028811985672E-02; weight( 4) = 0.22734860707492547802810838362671E-02; weight( 5) = 0.28772587656289004082883197417581E-02; weight( 6) = 0.34792893810051465908910894094105E-02; weight( 7) = 0.40792095178254605327114733456293E-02; weight( 8) = 0.46766539777779034772638165662478E-02; weight( 9) = 0.52712596565634400891303815906251E-02; weight( 10) = 0.58626653903523901033648343751367E-02; weight( 11) = 0.64505120486899171845442463868748E-02; weight( 12) = 0.70344427036681608755685893032552E-02; weight( 13) = 0.76141028256526859356393930849227E-02; weight( 14) = 0.81891404887415730817235884718726E-02; weight( 15) = 0.87592065795403145773316804234385E-02; weight( 16) = 0.93239550065309714787536985834029E-02; weight( 17) = 0.98830429087554914716648010899606E-02; weight( 18) = 0.10436130863141005225673171997668E-01; weight( 19) = 0.10982883090068975788799657376065E-01; weight( 20) = 0.11522967656921087154811609734510E-01; weight( 21) = 0.12056056679400848183529562144697E-01; weight( 22) = 0.12581826520465013101514365424172E-01; weight( 23) = 0.13099957986718627426172681912499E-01; weight( 24) = 0.13610136522139249906034237533759E-01; weight( 25) = 0.14112052399003395774044161633613E-01; weight( 26) = 0.14605400905893418351737288078952E-01; weight( 27) = 0.15089882532666922992635733981431E-01; weight( 28) = 0.15565203152273955098532590262975E-01; weight( 29) = 0.16031074199309941802254151842763E-01; weight( 30) = 0.16487212845194879399346060358146E-01; weight( 31) = 0.16933342169871654545878815295200E-01; weight( 32) = 0.17369191329918731922164721250350E-01; weight( 33) = 0.17794495722974774231027912900351E-01; weight( 34) = 0.18208997148375106468721469154479E-01; weight( 35) = 0.18612443963902310429440419898958E-01; weight( 36) = 0.19004591238555646611148901044533E-01; weight( 37) = 0.19385200901246454628112623489471E-01; weight( 38) = 0.19754041885329183081815217323169E-01; weight( 39) = 0.20110890268880247225644623956287E-01; weight( 40) = 0.20455529410639508279497065713301E-01; weight( 41) = 0.20787750081531811812652137291250E-01; weight( 42) = 0.21107350591688713643523847921658E-01; weight( 43) = 0.21414136912893259295449693233545E-01; weight( 44) = 0.21707922796373466052301324695331E-01; weight( 45) = 0.21988529885872983756478409758807E-01; weight( 46) = 0.22255787825930280235631416460158E-01; weight( 47) = 0.22509534365300608085694429903050E-01; weight( 48) = 0.22749615455457959852242553240982E-01; weight( 49) = 0.22975885344117206754377437838947E-01; weight( 50) = 0.23188206663719640249922582981729E-01; weight( 51) = 0.23386450514828194170722043496950E-01; weight( 52) = 0.23570496544381716050033676844306E-01; weight( 53) = 0.23740233018760777777714726703424E-01; weight( 54) = 0.23895556891620665983864481754172E-01; weight( 55) = 0.24036373866450369675132086026456E-01; weight( 56) = 0.24162598453819584716522917710986E-01; weight( 57) = 0.24274154023278979833195063936748E-01; weight( 58) = 0.24370972849882214952813561907241E-01; weight( 59) = 0.24452996155301467956140198471529E-01; weight( 60) = 0.24520174143511508275183033290175E-01; weight( 61) = 0.24572466031020653286354137335186E-01; weight( 62) = 0.24609840071630254092545634003360E-01; weight( 63) = 0.24632273575707679066033370218017E-01; weight( 64) = 0.24639752923961094419579417477503E-01; weight( 65) = 0.24632273575707679066033370218017E-01; weight( 66) = 0.24609840071630254092545634003360E-01; weight( 67) = 0.24572466031020653286354137335186E-01; weight( 68) = 0.24520174143511508275183033290175E-01; weight( 69) = 0.24452996155301467956140198471529E-01; weight( 70) = 0.24370972849882214952813561907241E-01; weight( 71) = 0.24274154023278979833195063936748E-01; weight( 72) = 0.24162598453819584716522917710986E-01; weight( 73) = 0.24036373866450369675132086026456E-01; weight( 74) = 0.23895556891620665983864481754172E-01; weight( 75) = 0.23740233018760777777714726703424E-01; weight( 76) = 0.23570496544381716050033676844306E-01; weight( 77) = 0.23386450514828194170722043496950E-01; weight( 78) = 0.23188206663719640249922582981729E-01; weight( 79) = 0.22975885344117206754377437838947E-01; weight( 80) = 0.22749615455457959852242553240982E-01; weight( 81) = 0.22509534365300608085694429903050E-01; weight( 82) = 0.22255787825930280235631416460158E-01; weight( 83) = 0.21988529885872983756478409758807E-01; weight( 84) = 0.21707922796373466052301324695331E-01; weight( 85) = 0.21414136912893259295449693233545E-01; weight( 86) = 0.21107350591688713643523847921658E-01; weight( 87) = 0.20787750081531811812652137291250E-01; weight( 88) = 0.20455529410639508279497065713301E-01; weight( 89) = 0.20110890268880247225644623956287E-01; weight( 90) = 0.19754041885329183081815217323169E-01; weight( 91) = 0.19385200901246454628112623489471E-01; weight( 92) = 0.19004591238555646611148901044533E-01; weight( 93) = 0.18612443963902310429440419898958E-01; weight( 94) = 0.18208997148375106468721469154479E-01; weight( 95) = 0.17794495722974774231027912900351E-01; weight( 96) = 0.17369191329918731922164721250350E-01; weight( 97) = 0.16933342169871654545878815295200E-01; weight( 98) = 0.16487212845194879399346060358146E-01; weight( 99) = 0.16031074199309941802254151842763E-01; weight(100) = 0.15565203152273955098532590262975E-01; weight(101) = 0.15089882532666922992635733981431E-01; weight(102) = 0.14605400905893418351737288078952E-01; weight(103) = 0.14112052399003395774044161633613E-01; weight(104) = 0.13610136522139249906034237533759E-01; weight(105) = 0.13099957986718627426172681912499E-01; weight(106) = 0.12581826520465013101514365424172E-01; weight(107) = 0.12056056679400848183529562144697E-01; weight(108) = 0.11522967656921087154811609734510E-01; weight(109) = 0.10982883090068975788799657376065E-01; weight(110) = 0.10436130863141005225673171997668E-01; weight(111) = 0.98830429087554914716648010899606E-02; weight(112) = 0.93239550065309714787536985834029E-02; weight(113) = 0.87592065795403145773316804234385E-02; weight(114) = 0.81891404887415730817235884718726E-02; weight(115) = 0.76141028256526859356393930849227E-02; weight(116) = 0.70344427036681608755685893032552E-02; weight(117) = 0.64505120486899171845442463868748E-02; weight(118) = 0.58626653903523901033648343751367E-02; weight(119) = 0.52712596565634400891303815906251E-02; weight(120) = 0.46766539777779034772638165662478E-02; weight(121) = 0.40792095178254605327114733456293E-02; weight(122) = 0.34792893810051465908910894094105E-02; weight(123) = 0.28772587656289004082883197417581E-02; weight(124) = 0.22734860707492547802810838362671E-02; weight(125) = 0.16683488125171936761028811985672E-02; weight(126) = 0.10622766869538486959954760554099E-02; weight(127) = 0.45645726109586654495731936146574E-03; else fprintf ( 1, '\n' ); fprintf ( 1, 'GL_WEIGHTS - Fatal error!\n' ); fprintf ( 1, ' Illegal value of ORDER = %d\n', order ); fprintf ( 1, ' Legal values are 1, 3, 7, 15, 31, 63 or 127.\n' ); error ( 'GL_WEIGHTS - Fatal error!' ); end return end function value = i4_choose ( n, k ) %*****************************************************************************80 % %% I4_CHOOSE computes the binomial coefficient C(N,K). % % Discussion: % % The value is calculated in such a way as to avoid overflow and % roundoff. The calculation is done in integer arithmetic. % % The formula used is: % % C(N,K) = N! / ( K! * (N-K)! ) % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 02 June 2007 % % 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, integer N, K, are the values of N and K. % % Output, integer VALUE, the number of combinations of N % things taken K at a time. % mn = min ( k, n - k ); if ( mn < 0 ) value = 0; elseif ( mn == 0 ) value = 1; else mx = max ( k, n - k ); value = mx + 1; for i = 2 : mn value = ( value * ( mx + i ) ) / i; end end return end function value = i4_log_2 ( i ) %*****************************************************************************80 % %% I4_LOG_2 returns the integer part of the logarithm base 2 of |I|. % % Discussion: % % For positive I4_LOG_2(I), it should be true that % 2**I4_LOG_2(X) <= |I| < 2**(I4_LOG_2(I)+1). % The special case of I4_LOG_2(0) returns -HUGE(). % % Example: % % I Value % % 0 -1 % 1, 0 % 2, 1 % 3, 1 % 4, 2 % 5, 2 % 6, 2 % 7, 2 % 8, 3 % 9, 3 % 10, 3 % 127, 6 % 128, 7 % 129, 7 % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 09 April 2004 % % Author: % % John Burkardt % % Parameters: % % Input, integer I, the number whose logarithm base 2 is desired. % % Output, integer VALUE, the integer part of the logarithm base 2 of % the absolute value of I. % i = floor ( i ); if ( i == 0 ) value = -inf; else value = 0; i = abs ( i ); while ( 2 <= i ) i = i / 2; value = value + 1; end end return end function value = i4_modp ( i, j ) %*****************************************************************************80 % %% 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. % % Example: % % I J MOD 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 August 2007 % % Author: % % John Burkardt % % Parameters: % % Input, integer I, the number to be divided. % % Input, integer J, the number that divides I. % % Output, integer VALUE, the nonnegative remainder when I is % divided by J. % if ( j == 0 ) fprintf ( 1, '\n' ); fprintf ( 1, 'I4_MODP - Fatal error!\n' ); fprintf ( 1, ' Illegal divisor J = %d\n', j ); error ( 'I4_MODP - Fatal error!' ); end value = mod ( i, j ); if ( value < 0 ) value = value + abs ( j ); end return end function grid_level = index_level_gl ( level, level_max, dim_num, ... point_num, grid_index, grid_base ) %*****************************************************************************80 % %% INDEX_LEVEL_GL: determine first level at which given index is generated. % % Discussion: % % We are constructing a sparse grid of Gauss-Legendre 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 % Gauss-Legendre abscissa is 0, the special "nested" value we need % to take care of. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 26 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, integer LEVEL, the level at which these points were % generated. LEVEL_MIN <= LEVEL <= LEVEL_MAX. % % Input, integer LEVEL_MAX, the maximum level. % % Input, integer DIM_NUM, the spatial dimension. % % Input, integer POINT_NUM, the number of points to be tested. % % Input, integer GRID_INDEX(DIM_NUM,POINT_NUM), the indices of the % points to be tested. % % Input, integer GRID_BASE(DIM_NUM), the "base", which is essentially % the denominator of the index. % % Output, integer GRID_LEVEL(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. % level_min = max ( 0, level_max + 1 - dim_num ); % % 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 = 1 : point_num grid_level(point) = max ( level, level_min ); for dim = 1 : dim_num if ( grid_index(dim,point) == 0 ) grid_level(point) = max ( grid_level(point) - grid_base(dim), level_min ); end end end return end function order = level_to_order_open ( dim_num, level ) %*****************************************************************************80 % %% LEVEL_TO_ORDER 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. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 18 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, integer DIM_NUM, the spatial dimension. % % Input, integer LEVEL(DIM_NUM), the nesting level. % % Output, integer ORDER(DIM_NUM), the order (number of points) of the rule. % for dim = 1 : dim_num if ( level(dim) < 0 ) order(dim) = -1; elseif ( level(dim) == 0 ) order(dim) = 1; else order(dim) = 2^( level(dim) + 1 ) - 1; end end return end function indx = multigrid_index_z ( dim_num, order_1d, order_nd ) %*****************************************************************************80 % %% MULTIGRID_INDEX_Z 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: % % 26 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, integer DIM_NUM, the spatial dimension of the points. % % Input, integer ORDER_1D(DIM_NUM), the order of the % rule in each dimension. % % Input, integer ORDER_ND, the product of the entries of ORDER_1D. % % Output, integer 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. % a = []; more = 0; p = 0; while ( 1 ) [ a, more ] = vec_colex_next2 ( dim_num, order_1d, a, more ); if ( ~more ) break end p = p + 1; % % 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. % indx(1:dim_num,p) = a(1:dim_num) - round ( ( order_1d(1:dim_num) - 1 ) / 2 ); end return end function w_nd = product_weight_gl ( dim_num, order_1d, order_nd ) %*****************************************************************************80 % %% PRODUCT_WEIGHT_GL: weights for a product Gauss-Legendre rule. % % Discussion: % % This routine computes the weights for a quadrature rule which is % a product of 1D Gauss-Legendre rules of varying order. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 26 September 2007 % % Author: % % John Burkardt % % Parameters: % % Input, integer DIM_NUM, the spatial dimension. % % Input, integer ORDER_1D(DIM_NUM), the order of the 1D rules. % % Input, integer ORDER_ND, the order of the product rule. % % Output, real W_ND(ORDER_ND), the product rule weights. % w_nd(1:order_nd) = 1.0; for dim = 1 : dim_num w_1d = gl_weights ( order_1d(dim) ); w_nd = r8vec_direct_product2 ( dim, order_1d(dim), w_1d, dim_num, ... order_nd, w_nd ); end return end function r8mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title ) %*****************************************************************************80 % %% R8MAT_TRANSPOSE_PRINT_SOME prints some of an R8MAT, transposed. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 23 May 2005 % % Author: % % John Burkardt % % Parameters: % % Input, integer M, N, the number of rows and columns. % % Input, real A(M,N), an M by N matrix to be printed. % % Input, integer ILO, JLO, the first row and column to print. % % Input, integer IHI, JHI, the last row and column to print. % % Input, string TITLE, an optional title. % incx = 5; if ( 0 < s_len_trim ( title ) ) fprintf ( 1, '\n' ); fprintf ( 1, '%s\n', title ); end for i2lo = max ( ilo, 1 ) : incx : min ( ihi, m ) i2hi = i2lo + incx - 1; i2hi = min ( i2hi, m ); i2hi = min ( i2hi, ihi ); inc = i2hi + 1 - i2lo; fprintf ( 1, '\n' ); fprintf ( 1, ' Row: ' ); for i = i2lo : i2hi fprintf ( 1, '%7d ', i ); end fprintf ( 1, '\n' ); fprintf ( 1, ' Col\n' ); j2lo = max ( jlo, 1 ); j2hi = min ( jhi, n ); for j = j2lo : j2hi fprintf ( 1, '%5d ', j ); for i2 = 1 : inc i = i2lo - 1 + i2; fprintf ( 1, '%12f', a(i,j) ); end fprintf ( 1, '\n' ); end end return end function r8mat_write ( output_filename, m, n, table ) %*****************************************************************************80 % %% R8MAT_WRITE writes an R8MAT file. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 09 August 2009 % % Author: % % John Burkardt % % Parameters: % % Input, string OUTPUT_FILENAME, the output filename. % % Input, integer M, the spatial dimension. % % Input, integer N, the number of points. % % Input, real TABLE(M,N), the points. % % % Open the file. % output_unit = fopen ( output_filename, 'wt' ); if ( output_unit < 0 ) fprintf ( 1, '\n' ); fprintf ( 1, 'R8MAT_WRITE - Error!\n' ); fprintf ( 1, ' Could not open the output file.\n' ); error ( 'R8MAT_WRITE - Error!' ); return; end % % Write the data. % % For greater precision, try: % % fprintf ( output_unit, ' %24,16f', table(i,j) ); % for j = 1 : n for i = 1 : m fprintf ( output_unit, ' %14f', table(i,j) ); end fprintf ( output_unit, '\n' ); end % % Close the file. % fclose ( output_unit ); return end function w = r8vec_direct_product2 ( factor_index, factor_order, ... factor_value, factor_num, point_num, w ) %*****************************************************************************80 % %% R8VEC_DIRECT_PRODUCT2 creates a direct product of R8VEC's. % % Discussion: % % 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: % % 18 April 2009 % % Author: % % John Burkardt % % Parameters: % % Input, integer FACTOR_INDEX, the index of the factor being processed. % The first factor processed must be factor 1. % % Input, integer FACTOR_ORDER, the order of the factor. % % Input, real FACTOR_VALUE(FACTOR_ORDER), the factor values for % factor FACTOR_INDEX. % % Input, integer FACTOR_NUM, the number of factors. % % Input, integer POINT_NUM, the number of elements in the direct product. % % Input/output, real W(POINT_NUM), the elements of the % direct product, updated by the latest factor. % % 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. % persistent contig; persistent rep; persistent skip; if ( factor_index == 1 ) contig = 1; skip = 1; rep = point_num; w(1:point_num) = 1.0; end rep = rep / factor_order; skip = skip * factor_order; for j = 1 : factor_order start = 1 + ( j - 1 ) * contig; for k = 1 : rep w(start:start+contig-1) = w(start:start+contig-1) * factor_value(j); start = start + skip; end end contig = contig * factor_order; return end function r8vec_print_some ( n, a, i_lo, i_hi, title ) %*****************************************************************************80 % %% R8VEC_PRINT_SOME prints "some" of an R8VEC. % % Discussion: % % An R8VEC is a vector of R8 values. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 16 October 2006 % % Author: % % John Burkardt % % Parameters: % % Input, integer N, the dimension of the vector. % % Input, real A(N), the vector to be printed. % % Input, integer MAX_PRINT, the maximum number of lines to print. % % Input, string TITLE, an optional title. % if ( 0 < s_len_trim ( title ) ) fprintf ( 1, '\n' ); fprintf ( 1, '%s\n', title ); end fprintf ( 1, '\n' ); for i = max ( 1, i_lo ) : min ( n, i_hi ) fprintf ( 1, ' %8d %12f\n', i, a(i) ); end return end function len = s_len_trim ( s ) %*****************************************************************************80 % %% S_LEN_TRIM returns the length of a character string to the last nonblank. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 14 June 2003 % % Author: % % John Burkardt % % Parameters: % % Input, string S, the string to be measured. % % Output, integer LENGTH, the length of the string up to the last nonblank. % len = length ( s ); while ( 0 < len ) if ( s(len) ~= ' ' ) return end len = len - 1; end return end function [ grid_weight, grid_point ] = sparse_grid_gl ( dim_num, level_max, ... point_num ) %*****************************************************************************80 % %% SPARSE_GRID_GL computes a sparse grid of Gauss-Legendre points. % % Discussion: % % The quadrature rule is associated with a sparse grid derived from % a Smolyak construction using a 1D Gauss-Legendre quadrature rule. % % The user specifies: % * the spatial dimension of the quadrature region, % * the level that defines the Smolyak grid. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 04 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, integer DIM_NUM, the spatial dimension. % % Input, integer LEVEL_MAX, controls the size of the % sparse grid. % % Input, integer POINT_NUM, the number of points in the grid, % as determined by SPARSE_GRID_GL_SIZE. % % Output, real GRID_WEIGHT(POINT_NUM), the weights. % % Output, real GRID_POINT(DIM_NUM,POINT_NUM), the points. % grid_weight(1:point_num) = 0.0; % % The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. % point_num2 = 0; level_min = max ( 0, level_max + 1 - dim_num ); for level = level_min : level_max % % The middle loop generates the next partition LEVEL_1D(1:DIM_NUM) % that adds up to LEVEL. % level_1d = []; more = 0; h = 0; t = 0; while ( 1 ) [ level_1d, more, h, t ] = 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. % order_1d = level_to_order_open ( dim_num, level_1d ); grid_base2(1:dim_num) = round ( ( order_1d(1:dim_num) - 1 ) / 2 ); % % The product of the 1D orders gives us the number of points in this subgrid. % order_nd = prod ( order_1d(1:dim_num) ); % % Compute the weights for this product grid. % grid_weight2 = product_weight_gl ( dim_num, order_1d, order_nd ); % % Now determine the coefficient of the weight. % coeff = (-1)^( level_max - level ) ... * i4_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_z ( dim_num, order_1d, order_nd ); % % Determine the first level of appearance of each of the points. % This allows us to flag certain points as being repeats of points % generated on a grid of lower level. % % This is SLIGHTLY tricky. % grid_level = index_level_gl ( level, level_max, dim_num, order_nd, ... grid_index2, grid_base2 ); % % Only keep those points which first appear on this level. % for point = 1 : order_nd % % Either a "new" point (increase count, create point, create weight) % if ( grid_level(point) == level ) point_num2 = point_num2 + 1; grid_point(1:dim_num,point_num2) = gl_abscissa ( dim_num, 1, ... grid_index2(1:dim_num,point), grid_base2(1:dim_num) ); grid_weight(point_num2) = coeff * grid_weight2(point); % % or an already existing point (create point temporarily, find match, % add weight to matched point's weight). % else grid_point_temp(1:dim_num) = gl_abscissa ( dim_num, 1, ... grid_index2(1:dim_num,point), grid_base2(1:dim_num) ); point3 = -1; for point2 = 1 : point_num2 if ( grid_point(1:dim_num,point2) == grid_point_temp(1:dim_num)' ) point3 = point2; break end end if ( point3 == -1 ) fprintf ( 1, '\n' ); fprintf ( 1, 'SPARSE_GRID_GL - Fatal error!\n' ); fprintf ( 1, ' Could not match point.\n' ); error ( 'SPARSE_GRID_GL - Fatal error!' ); end grid_weight(point3) = grid_weight(point3) + coeff * grid_weight2(point); end end if ( ~more ) break end end end return end function [ grid_index, grid_base ] = sparse_grid_gl_index ( dim_num, ... level_max, point_num ) %*****************************************************************************80 % %% SPARSE_GRID_GL_INDEX indexes the points forming a sparse grid of GL points. % % Discussion: % % The sparse grid is assumed to be formed from 1D Gauss-Legendre rules % of ODD order, which have the property that only the central abscissa, % X = 0.0, is "nested". % % The necessary dimensions of GRID_INDEX can be determined by % calling SPARSE_GRID_GL_SIZE first. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 04 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, integer DIM_NUM, the spatial dimension. % % Input, integer LEVEL_MAX, the maximum value of LEVEL. % % Input, integer POINT_NUM, the total number of points in % the grids. % % Output, integer 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, integer GRID_BASE(DIM_NUM,POINT_NUM), a list of % the orders of the Gauss-Legendre rules associated with each point % and dimension. % % % The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. % point_num2 = 0; level_min = max ( 0, level_max + 1 - dim_num ); for level = level_min : level_max % % The middle loop generates the next partition LEVEL_1D(1:DIM_NUM) % that adds up to LEVEL. % level_1d = []; more = false; h = 0; t = 0; while ( 1 ) [ level_1d, more, h, t ] = 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. % order_1d = level_to_order_open ( dim_num, level_1d ); grid_base2(1:dim_num) = round ( ( order_1d(1:dim_num) - 1 ) / 2 ); % % The product of the 1D orders gives us the number of points in this subgrid. % order_nd = prod ( order_1d(1:dim_num) ); % % 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_z ( dim_num, order_1d, order_nd ); % % Determine the first level of appearance of each of the points. % This allows us to flag certain points as being repeats of points % generated on a grid of lower level. % % This is SLIGHTLY tricky. % grid_level = index_level_gl ( level, level_max, dim_num, order_nd, ... grid_index2, grid_base2 ); % % Only keep those points which first appear on this level. % for point = 1 : order_nd if ( grid_level(point) == level ) point_num2 = point_num2 + 1; grid_index(1:dim_num,point_num2) = grid_index2(1:dim_num,point); grid_base(1:dim_num,point_num2) = grid_base2(1:dim_num); end end if ( ~more ) break end end end return end function point_num = sparse_grid_gl_size ( dim_num, level_max ) %*****************************************************************************80 % %% SPARSE_GRID_GL_SIZE sizes a sparse grid of Gauss-Legendre points. % % Discussion: % % The grid is defined as the sum of the product rules whose LEVEL % satisfies: % % LEVEL_MIN <= LEVEL <= LEVEL_MAX. % % where LEVEL_MAX is user specified, and % % LEVEL_MIN = max ( 0, LEVEL_MAX + 1 - DIM_NUM ). % % The grids are only very weakly nested, since Gauss-Legendre rules % only have the origin in common. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 04 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, integer DIM_NUM, the spatial dimension. % % Input, integer LEVEL_MAX, the maximum value of LEVEL. % % Output, integer POINT_NUM, the number of points in the grid. % % % Special case. % if ( level_max == 0 ) point_num = 1; return; end % % The outer loop generates LEVELs from LEVEL_MIN to LEVEL_MAX. % point_num = 0; level_min = max ( 0, level_max + 1 - dim_num ); for level = level_min : level_max % % The middle loop generates the next partition that adds up to LEVEL. % level_1d = []; more = false; h = 0; t = 0; while ( 1 ) [ level_1d, more, h, t ] = comp_next ( level, dim_num, level_1d, more, h, t ); % % Transform each 1D level to a corresponding 1D order. % order_1d = level_to_order_open ( dim_num, level_1d ); for dim = 1 : dim_num % % If we can reduce the level in this dimension by 1 and % still not go below LEVEL_MIN. % if ( level_min < level & 1 < order_1d(dim) ) order_1d(dim) = order_1d(dim) - 1; end end point_num = point_num + prod ( order_1d(1:dim_num) ); if ( ~more ) break end end end return end function timestamp ( ) %*****************************************************************************80 % %% TIMESTAMP prints the current YMDHMS date as a timestamp. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 14 February 2003 % % Author: % % John Burkardt % t = now; c = datevec ( t ); s = datestr ( c, 0 ); fprintf ( 1, '%s\n', s ); return end function [ a, more ] = vec_colex_next2 ( dim_num, base, a, more ) %*****************************************************************************80 % %% 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,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: % % 11 November 2007 % % Author: % % John Burkardt % % Reference: % % Dennis Stanton, Dennis White, % Constructive Combinatorics, % Springer, 1986, % ISBN: 0387963472, % LC: QA164.S79. % % Parameters: % % Input, integer DIM_NUM, the spatial dimension. % % Input, integer BASE(DIM_NUM), the base to be used in each dimension. % % Input, integer A(DIM_NUM), except on the first call, this should % be the output value of A on the last call. % % Input, logical MORE, should be FALSE on the first call, and % thereafter should be the output value of MORE from the previous call. % % Output, integer A(DIM_NUM), the next vector. % % Output, logical MORE, is TRUE if another vector was computed. % If MORE is FALSE on return, then ignore the output value A, and % stop calling the routine. % if ( ~more ) a(1:dim_num) = 0; more = 1; else for i = 1 : dim_num a(i) = a(i) + 1; if ( a(i) < base(i) ) return end a(i) = 0; end more = 0; end return end