static double test02(int dim_num, IntegratingFunction func) { double[] a = new double[dim_num]; double[] b = new double[dim_num]; int eval_num; double result; // // Set the integration limits. // // a(1:dim_num) = 0.0D+00 // b(1:dim_num) = 1.0D+00 for (int i = 0; i < dim_num; i++) { a[i] = 0.0D; b[i] = 1.0D; } result = NINTLIB.NINTLIB.p5_nd(func, dim_num, a, b, out eval_num); Console.WriteLine(" P5_ND: " + result + "," + eval_num); return(result); }
static double test06(int dim_num, IntegratingFunction func) { const int test_num = 3; double[] a = new double[dim_num]; double[] b = new double[dim_num]; int eval_num; double result = 0.0D; int seed; int test; seed = 123456789; // // Set the integration limits. // for (int i = 0; i < dim_num; i++) { a[i] = 0.0D; b[i] = 1.0D; } for (test = 1; test <= test_num; test++) { eval_num = (int)Math.Pow(8, test) * 10000; result = NINTLIB.NINTLIB.monte_carlo_nd(func, dim_num, a, b, eval_num, seed); Console.WriteLine(" MONTE_CARLO_ND: " + result + "," + eval_num); } return(result); }
static double test05(int dim_num, IntegratingFunction func) { double[] a = new double[dim_num]; double[] b = new double[dim_num]; int eval_num; int eval_total; int i; int igrid; int j; int ngrid; double result; double result_total = 0.0D; double[] xlo = new double[dim_num]; double[] xhi = new double[dim_num]; // xlo(1:dim_num) = 0.0D+00 // xhi(1:dim_num) = 1.0D+00 for (int k = 0; k < dim_num; k++) { xlo[k] = 0.0D; xhi[k] = 1.0D; } for (igrid = 1; igrid <= 6; igrid++) { ngrid = (int)Math.Pow(2, igrid - 1); result_total = 0.0D; eval_total = 0; for (i = 1; i <= ngrid; i++) { a[0] = ((ngrid - i + 1) * xlo[0] + (i - 1) * xhi[0]) / ngrid; b[0] = ((ngrid - i) * xlo[0] + i * xhi[0]) / (ngrid); for (j = 1; j <= ngrid; j++) { a[1] = ((ngrid - j + 1) * xlo[1] + (j - 1) * xhi[1]) / (ngrid); b[1] = ((ngrid - j) * xlo[1] + j * xhi[1]) / ngrid; result = NINTLIB.NINTLIB.p5_nd(func, dim_num, a, b, out eval_num); result_total = result_total + result; eval_total = eval_total + eval_num; } } Console.WriteLine(" P5_ND+: " + result_total + "," + eval_total); } return(result_total); }
static void testnd(int dim_num, IntegratingFunction func) { test01(dim_num, func); test02(dim_num, func); test03(dim_num, func); test04(dim_num, func); // // TEST05 is only set up for DIM_NUM = 2. // if (dim_num == 2) { test05(dim_num, func); } test06(dim_num, func); }
static double test01(int dim_num, IntegratingFunction func) { const int order = 5; int eval_num; double[] wtab = new double[order] { 0.236926885056189087514264040720D, 0.478628670499366468041291514836D, 0.568888888888888888888888888889D, 0.478628670499366468041291514836D, 0.236926885056189087514264040720D }; double[] wtab2 = new double[order]; double[] xtab = new double[order] { -0.906179845938663992797626878299D, -0.538469310105683091036314420700D, 0.0D, 0.538469310105683091036314420700D, 0.906179845938663992797626878299D }; double[] xtab2 = new double[order]; // // Adjust the quadrature rule from [-1,1] to [0,1]: // // xtab2(1:order) = ( xtab(1:order) + 1.0D+00 ) / 2.0D+00 // wtab2(1:order) = 0.5D+00 * wtab(1:order) for (int i = 0; i < order; i++) { xtab2[i] = (xtab[i] + 1.0D) / 2.0D; wtab2[i] = 0.5D * wtab[i]; } double result = NINTLIB.NINTLIB.box_nd(func, dim_num, order, xtab2, wtab2, out eval_num); Console.WriteLine(" BOX_ND: " + result + ", " + eval_num); return(result); }
static void test04(int dim_num, IntegratingFunction func) { const int k2 = 4; double[] dev1 = new double[k2]; double[] dev2 = new double[k2]; double[] err1 = new double[k2]; double[] est1 = new double[k2]; double[] est2 = new double[k2]; double[] err2 = new double[k2]; int eval_num; int k1; k1 = 1; NINTLIB.NINTLIB.sample_nd(func, k1, k2, dim_num, ref est1, ref err1, ref dev1, ref est2, ref err2, ref dev2, out eval_num); Console.WriteLine(" SAMPLE_ND: " + est2[k2 - 1] + "," + eval_num); }
static double test03(int dim_num, IntegratingFunction func) { double[] a = new double[dim_num]; double[] b = new double[dim_num]; int eval_num; int ind = 0; const int it_max = 2; double result; int[] sub_num = new int[dim_num]; double tol; // // Set the integration limits. // // a(1:dim_num) = 0.0D+00 // b(1:dim_num) = 1.0D+00 for (int i = 0; i < dim_num; i++) { a[i] = 0.0D; b[i] = 1.0D; } tol = 0.001D; // sub_num(1:dim_num) = 10 for (int i = 0; i < dim_num; i++) { sub_num[i] = 10; } result = NINTLIB.NINTLIB.romberg_nd(func, a, b, dim_num, sub_num, it_max, tol, ref ind, out eval_num); Console.WriteLine(" ROMBERG_ND: " + result + "," + eval_num); return(result); }
public static double sum2_nd(IntegratingFunction func, double[,] xtab, double[,] weight, int[] order, int dim_num, out int eval_num) /* * ! SUM2_ND estimates a multidimensional integral using a product rule. * ! * ! Discussion: * ! * ! The routine uses a product rule supplied by the user. * ! * ! The region may be a product of any combination of finite, * ! semi-infinite, or infinite intervals. * ! * ! For each factor in the region, it is assumed that an integration * ! rule is given, and hence, the region is defined implicitly by * ! the integration rule chosen. * ! * ! Licensing: * ! * ! This code is distributed under the GNU LGPL license. * ! * ! Modified: * ! * ! 25 February 2007 * ! * ! Author: * ! * ! Original FORTRAN77 version by Philip Davis, Philip Rabinowitz. * ! FORTRAN90 version by John Burkardt * ! C# version by Rafael Sales and Francisco Heron de Carvalho Junior (MDCC/UFC) * ! * ! Reference: * ! * ! Philip Davis, Philip Rabinowitz, * ! Methods of Numerical Integration, * ! Second Edition, * ! Dover, 2007, * ! ISBN: 0486453391, * ! LC: QA299.3.D28. * ! * ! Parameters: * ! * ! Input, delegate IntegratingFunction, a routine which evaluates * ! the function to be integrated, of the form: * ! * ! double func (double[] x) { * ! // x.Length == dim_num * ! ... * ! } * ! * ! Input, double[,] xtab(dim_num,order_max). xtab(i,j) is the * ! i-th abscissa of the j-th rule (xtab.Length = dim_num X order_max). * ! * ! Input, double[,] weigth. weigth(i,j) is the * ! i-th weight for the j-th rule (weigth.Length = dim_num X order_max). * ! * ! Input, int[] order. order(i) is the number of * ! abscissas to be used in the j-th rule. order(i) must be * ! greater than 0 and less than or equal to order_max (order.Length = dim_num). * ! * ! Input, int dim_num, the spatial dimension. * ! * ! Output, int eval_num, the number of function evaluations. * ! * ! Returns: * ! * ! double, the approximate value of the integral. * !*/ { double result; int i; int[] iwork = new int[dim_num]; int k; int m1; double w1; double[] work = new double[dim_num]; //Default values: result = 0.0D; eval_num = 0; if (dim_num < 1) { Console.Write("SUM2_ND - Fatal error!!"); Console.Write(" DIM_NUM < 1"); Console.Write(" DIM_NUM = {0}", dim_num); return(-1); } for (i = 0; i < dim_num; i++) { if (order[i] < 1) { Console.Write("SUM2_ND - Fatal error!"); Console.Write(" ORDER[I] < 1."); Console.Write(" For I = {0}", i); Console.Write(" ORDER[I] = {0}", order[i]); return(-1); } } for (k = 0; i < dim_num; i++) { iwork[k] = 0; } while (true) { k = 0; w1 = 1.0D; for (i = 0; i < dim_num; i++) { m1 = iwork[i]; work[i] = xtab[i, m1]; w1 = w1 * weight[i, m1]; } result = result + w1 * func(work); eval_num = eval_num + 1; while (iwork[k] == order[k]) { iwork[k] = 0; k = k + 1; if (dim_num <= k) { return(result); } ; } iwork[k] = iwork[k] + 1; } }
public static void sample_nd(IntegratingFunction func, int k1, int k2, int dim_num, ref double[] est1, ref double[] err1, ref double[] dev1, ref double[] est2, ref double[] err2, ref double[] dev2, out int eval_num) /* * !*****************************************************************************80 * ! * !! SAMPLE_ND estimates a multidimensional integral using sampling. * ! * ! Discussion: * ! * ! This routine computes two sequences of integral estimates, EST1 * ! and EST2, for indices K going from K1 to K2. These estimates are * ! produced by the generation of 'random' abscissas in the region. * ! The process can become very expensive if high accuracy is needed. * ! * ! The total number of function evaluations is * ! 4*(K1**DIM_NUM+(K1+1)**DIM_NUM+...+(K2-1)**DIM_NUM+K2**DIM_NUM), and K2 * ! should be chosen so as to make this quantity reasonable. * ! In most situations, EST2(K) are much better estimates than EST1(K). * ! * ! Licensing: * ! * ! This code is distributed under the GNU LGPL license. * ! * ! Modified: * ! * ! 01 March 2007 * ! * ! Author: * ! * ! Original FORTRAN77 version by Philip Davis, Philip Rabinowitz. * ! FORTRAN90 version by John Burkardt * ! C# version by Rafael Sales * ! * ! Reference: * ! * ! Philip Davis, Philip Rabinowitz, * ! Methods of Numerical Integration, * ! Second Edition, * ! Dover, 2007, * ! ISBN: 0486453391, * ! LC: QA299.3.D28. * ! * ! Parameters: * ! * ! Input, delegate IntegratingFunction, a routine which evaluates * ! the function to be integrated, of the form: * ! * ! double func (double[] x) { * ! // x.Length == dim_num * ! ... * ! } * ! * ! Input, int k1, the beginning index for the iteration. * ! 1 <= k1 <= k2. * ! * ! Input, int k2, the final index for the iteration. k1 <= k2. * ! Increasing k2 increases the accuracy of the calculation, * ! but vastly increases the work and running time of the code. * ! * ! Input, int dim_num, the spatial dimension. 1 <= dim_num <= 10. * ! * ! Output, double[] est1. Entries k1 through k2 contain * ! successively better estimates of the integral (est1.Length = k2). * ! * ! Output, double[] err1. Entries k1 through k2 contain * ! the corresponding estimates of the integration errors (err1.Length = k2). * ! * ! Output, double[] dev1. Entries k1 through k2 contain * ! estimates of the reliability of the the integration. * ! If consecutive values dev1(k) and dev1(k+1) do not differ * ! by more than 10 percent, then err1(k) can be taken as * ! a reliable upper bound on the difference between est1(k) * ! and the true value of the integral (dev1.Length = k2). * ! * ! Output, double[] est2. Entries k2 through k2 contain * ! successively better estimates of the integral (est2.Length = k2). * ! * ! Output, double[] err2. Entries k2 through k2 contain * ! the corresponding estimates of the integration errors (err2.Length = k2). * ! * ! Output, double[] dev2. Entries k2 through k2 contain * ! estimates of the reliability of the the integration. * ! If consecutive values dev2(k) and dev2(k+2) do not differ * ! by more than 10 percent, then err2(k) can be taken as * ! a reliable upper bound on the difference between est2(k) * ! and the true value of the integral (dev2.Length = k2). * ! * ! Output, int eval_num, the number of function evaluations. * !*/ { int dim_max = 10; //integer ( kind = 4 ), parameter :: dim_max = 10 double ak; double ak1; double akn; double[] al = new double[] { 0.4142135623730950D + 00, 0.7320508075688773D + 00, 0.2360679774997897D + 00, 0.6457513110645906D + 00, 0.3166247903553998D + 00, 0.6055512754639893D + 00, 0.1231056256176605D + 00, 0.3589989435406736D + 00, 0.7958315233127195D + 00, 0.3851648071345040D + 00 }; double b; double[] be = new double[dim_num]; double bk; double d1; double d2; double[] dex = new double[dim_num]; double g; double[] ga = new double[dim_num]; int key; bool more; double[] p1 = new double[dim_num]; double[] p2 = new double[dim_num]; double[] p3 = new double[dim_num]; double[] p4 = new double[dim_num]; double s1; double s2; double t; double y1; double y2; double y3; double y4; eval_num = 0; //Check input if (dim_num < 1) { Console.Write("SAMPLE_ND - Fatal error!"); Console.Write("DIM_NUM must be at least 1,"); Console.Write("but DIM_NUM = {0}", dim_num); return; } if (dim_max < dim_num) { Console.Write("SAMPLE_ND - Fatal error!"); Console.Write(" DIM_NUM must be no more than DIM_MAX = {0}", dim_max); Console.Write(" but DIM_NUM = {0}", dim_num); return; } if (k1 < 0) { Console.Write("SAMPLE_ND - Fatal error!"); Console.Write(" K1 must be at least 1, but K1 = {0}", k1); return; } if (k2 < k1) { Console.Write("SAMPLE_ND - Fatal error!"); Console.Write(" K1 may not be greater than K2, but '"); Console.Write(" K1 = {0}", k1); Console.Write(" K2 = {0}", k2); return; } Array.Copy(al, be, dim_num); //be(1:dim_num) = al(1:dim_num) Array.Copy(al, ga, dim_num); //ga(1:dim_num) = al(1:dim_num) for (int i = 0; i < dim_num; i++) { dex[i] = 0.0D; //dex(1:dim_num) = 0.0D+00 } for (int k = k1; k <= k2; k++) { ak = k; key = 0; ak1 = ak - 1.1D; s1 = 0.0D; d1 = 0.0D; s2 = 0.0D; d2 = 0.0D; akn = Math.Pow(ak, dim_num); //akn = ak**dim_num t = Math.Sqrt(Math.Pow(ak, dim_num)) * ak; //t = sqrt ( ak**dim_num ) * ak bk = 1.0D / ak; while (true) { key = key + 1; if (key != 1) { key = key - 1; more = false; for (int j = 0; j < dim_num; j++) { if (dex[j] <= ak1) { dex[j] = dex[j] + 1.0D; more = true; break; } dex[j] = 0.0D; } if (!more) { break; } } for (int i = 0; i < dim_num; i++) { b = be[i] + al[i]; if (1.0D < b) { b = b - 1.0D; } g = ga[i] + b; if (1.0D < g) { g = g - 1.0D; } be[i] = b + al[i]; if (1.0D < be[i]) { be[i] = be[i] - 1.0D; } ga[i] = be[i] + g; if (1.0D < ga[i]) { ga[i] = ga[i] - 1.0D; } p1[i] = (dex[i] + g) * bk; p2[i] = (dex[i] + 1.0D - g) * bk; p3[i] = (dex[i] + ga[i]) * bk; p4[i] = (dex[i] + 1.0D - ga[i]) * bk; } y1 = func(p1); eval_num = eval_num + 1; /* There may be an error in the next two lines, * but oddly enough, that is how the original reads */ y3 = func(p2); eval_num = eval_num + 1; y2 = func(p3); eval_num = eval_num + 1; y4 = func(p4); eval_num = eval_num + 1; s1 = s1 + y1 + y2; d1 = d1 + Math.Pow(y1 - y2, 2); //d1 = d1 + ( y1 - y2 )**2; s2 = s2 + y3 + y4; d2 = d2 + Math.Pow(y1 + y3 - y2 - y4, 2); //d2 = d2 + ( y1 + y3 - y2 - y4 )**2; } int kk = k - 1; est1[kk] = 0.5D * s1 / akn; err1[kk] = 1.5D * Math.Sqrt(d1) / akn; dev1[kk] = err1[kk] * t; est2[kk] = 0.25D * (s1 + s2) / akn; err2[kk] = 0.75D * Math.Sqrt(d2) / akn; dev2[kk] = err2[kk] * t * ak; } }
public static double romberg_nd(IntegratingFunction func, double[] a, double[] b, int dim_num, int[] sub_num, int it_max, double tol, ref int ind, out int eval_num) /* * !*****************************************************************************80 * ! * !! ROMBERG_ND estimates a multidimensional integral using Romberg integration. * ! * ! Discussion: * ! * ! The routine uses a Romberg method based on the midpoint rule. * ! * ! In the reference, this routine is called "NDIMRI". * ! * ! Thanks to Barak Bringoltz for pointing out problems in a previous * ! FORTRAN90 implementation of this routine. * ! * ! Licensing: * ! * ! This code is distributed under the GNU LGPL license. * ! * ! Modified: * ! * ! 11 September 2006 * ! * ! Author: * ! * ! Original FORTRAN77 version by Philip Davis, Philip Rabinowitz. * ! FORTRAN90 version by John Burkardt * ! C# version by Francisco Heron de Carvalho Junior (MDCC/UFC) * ! * ! Reference: * ! * ! Philip Davis, Philip Rabinowitz, * ! Methods of Numerical Integration, * ! Second Edition, * ! Dover, 2007, * ! ISBN: 0486453391, * ! LC: QA299.3.D28. * ! * ! Parameters: * ! * ! Input, delegate IntegratingFunction, a routine which evaluates * ! the function to be integrated, of the form: * ! * ! double func (double[] x) { * ! // x.Length == dim_num * ! ... * ! } * ! * ! Input, int dim_num, the spatial dimension. * ! * ! Input, double[] a, b, the integration limits (a.Length = b.Length = dim_num). * ! * ! Input, int[] sub_num, the number of subintervals into * ! which the i-th integration interval (a(i), b(i)) is * ! initially subdivided. sub_num(i) must be greater than 0 (sub_num.Length = dim_num). * ! * ! Input, int it_max, the maximum number of iterations to * ! be performed. The number of function evaluations on * ! iteration j is at least Math.Pow(j,dim_num), which grows very rapidly. * ! it_max should be small! * ! * ! Input, double tol, an error tolerance for the approximation * ! of the integral. * ! * ! Output, int ind, error return flag. * ! ind = -1 if the error tolerance could not be achieved. * ! ind = 1 if the error tolerance was achieved. * ! * ! Output, int eval_num, the number of function evaluations. * ! * ! Local Parameters: * ! * ! Local, int[] iwork, a pointer used to generate all the * ! points X in the product region (iwork.Length = dim_num). * ! * ! Local, int[] iwork2, a counter of the number of points * ! used at each step of the Romberg iteration (iwork2.Length = it_max). * ! * ! Local, int[] sub_num2, the number of subintervals used * ! in each direction, a refinement of the user's input sub_num (sub_num2.Length = dim_num). * ! * ! Local, double[] table, the difference table (table.Length = it_max). * ! * ! Local, double[] x, an evaluation point (x.Length = dim_num). * ! * ! Returns: * ! * ! double, the approximate value of the integral. * ! */ { double factor; int i; int it; int[] iwork = new int[dim_num]; int[] iwork2 = new int[it_max + 1]; int kdim; int ll; int[] sub_num2 = new int[dim_num]; double result, result_old = 0, rnderr = 0.0D, sum1, weight = 0; double[] table = new double[it_max + 1]; double[] x = new double[dim_num]; eval_num = 0; if (dim_num < 1) { Console.WriteLine("ROMBERG_ND - Fatal error!"); Console.WriteLine(" DIM_NUM is less than 1. DIM_NUM = " + dim_num); return(-1); } if (it_max < 0) { Console.WriteLine("ROMBERG_ND - Fatal error!"); Console.WriteLine(" IT_MAX is less than 0. IT_MAX = " + it_max); return(-1); } for (i = 0; i < dim_num; i++) { if (sub_num[i] <= 0) { Console.WriteLine("ROMBERG_ND - Fatal error!"); Console.WriteLine(" SUB_NUM(I) is less than 1."); Console.WriteLine(" for I = " + i); Console.WriteLine(" SUB_NUM(I) = " + sub_num[i]); return(-1); } } ind = 0; //rnderr = epsilon (1.0D); rnderr = Math.Pow(2, -95); iwork2[0] = 1; // sub_num2(1:dim_num) = sub_num(1:dim_num) for (int k = 0; k < dim_num; k++) { sub_num2[k] = sub_num[k]; } if (0 < it_max) { iwork2[1] = 2; } it = 0; while (true) { sum1 = 0.0D; // weight = product ( ( b(1:dim_num) - a(1:dim_num) ) / real ( sub_num2(1:dim_num), kind = 8 ) ) weight = 1.0D;; for (int k = 0; k < dim_num; k++) { weight *= (b[k] - a[k]) / sub_num2[k]; } // // Generate every point X in the product region, and evaluate F(X). // for (int k = 0; k < dim_num; k++) { iwork[k] = 1; } while (true) { // x(1:dim_num) = ( real ( 2 * sub_num2(1:dim_num) - 2 * iwork(1:dim_num) + 1, kind = 8 ) * a(1:dim_num) + real (+ 2 * iwork(1:dim_num) - 1, kind = 8 ) * b(1:dim_num) ) / real ( 2 * sub_num2(1:dim_num), kind = 8 ) for (int k = 0; k < dim_num; k++) { x[k] = ((2 * sub_num2[k] - 2 * iwork[k] + 1) * a[k] + (2 * iwork[k] - 1) * b[k]) / (2 * sub_num2[k]); } sum1 += func(x); eval_num += 1; kdim = dim_num - 1; while (0 <= kdim) { if (iwork[kdim] < sub_num2[kdim]) { iwork[kdim]++; break; } iwork[kdim] = 1; kdim--; } if (kdim < 0) { break; } } // // Done with summing. // table[it] = weight * sum1; if (it <= 0) { result = table[0]; result_old = result; if (it_max <= it) { ind = 0; break; } it = it + 1; // sub_num2(1:dim_num) = iwork2(it) * sub_num2(1:dim_num) for (int k = 0; k < dim_num; k++) { sub_num2[k] *= iwork2[it]; } continue; } // // Compute the difference table for Richardson extrapolation. // for (ll = 1; ll <= it; ll++) { i = it - ll; factor = Math.Pow(iwork2[i], 2) / (Math.Pow(iwork2[it], 2) - Math.Pow(iwork2[i], 2)); table[i] = table[i + 1] + (table[i + 1] - table[i]) * factor; } result = table[0]; // // Terminate successfully if the estimated error is acceptable. // if (Math.Abs(result - result_old) <= Math.Abs(result * (tol + rnderr))) { ind = 1; break; } // // Terminate unsuccessfully if the iteration limit has been reached. // if (it_max <= it) { ind = -1; break; } // // Prepare for another step. // result_old = result; it++; iwork2[it] = (int)(1.5D * iwork2[it - 1]); for (int k = 0; k < dim_num; k++) { sub_num2[k] = (int)(1.5D * sub_num2[k]); } } return(result); }
public static double p5_nd(IntegratingFunction func, int dim_num, double[] a, double[] b, out int eval_num) /*!*****************************************************************************80 * ! * !! P5_ND estimates a multidimensional integral with a formula of exactness 5. * ! * ! Discussion: * ! * ! The routine uses a method which is exact for polynomials of total * ! degree 5 or less. * ! * ! Licensing: * ! * ! This code is distributed under the GNU LGPL license. * ! * ! Modified: * ! * ! 11 September 2006 * ! * ! Author: * ! * ! Original FORTRAN77 version by Philip Davis, Philip Rabinowitz. * ! FORTRAN90 version by John Burkardt * ! C# version by Rafael Sales and Francisco Heron de Carvalho Junior (MDCC/UFC) * ! * ! Reference: * ! * ! Philip Davis, Philip Rabinowitz, * ! Methods of Numerical Integration, * ! Second Edition, * ! Dover, 2007, * ! ISBN: 0486453391, * ! LC: QA299.3.D28. * ! * ! Parameters: * ! * ! Input, delegate IntegratingFunction, a routine which evaluates * ! the function to be integrated, of the form: * ! * ! double func (double[] x) { * ! // x.Length == dim_num * ! ... * ! } * ! * ! Input, int dim_num, the spatial dimension. * ! * ! Input, double[] a, b, the integration limits (a.Length = b.Length = dim_num). * ! * ! Output, int eval_num, the number of function evaluations. * ! * ! Returns: * ! * ! double, the approximate value of the integral. * */ { double a0, a1, a2, a3, a4, a5; double en; double sum1, sum2, sum3; double volume; double[] work = new double[dim_num]; double result; eval_num = 0; if (dim_num < 1) { Console.Write("P5_ND - Fatal error!"); Console.Write(" DIM_NUM < 1, DIM_NUM = {0}", dim_num); return(-1.0D); } a2 = 25.0D / 324.0D; a3 = Math.Sqrt(0.6D); en = dim_num; a0 = (25.0D * en * en - 115.0D * en + 162.0D) / 162.0D; a1 = (70.0D - 25.0D * en) / 162.0D; //volume = product ( b(1:dim_num) - a(1:dim_num) ) //work(1:dim_num) = 0.5D+00 * ( a(1:dim_num) + b(1:dim_num) ) volume = 1; for (int i = 0; i < dim_num; i++) { volume *= (b[i] - a[i]); work[i] = 0.5D * (a[i] + b[i]); } result = 0.0D; if (volume == 0.0D) { Console.Write("P5_ND - Warning!"); Console.Write(" Volume = 0, integral = 0."); return(0.0D); } sum1 = a0 * func(work); eval_num = eval_num + 1; sum2 = 0.0D; sum3 = 0.0D; for (int i = 0; i < dim_num; i++) { work[i] = 0.5D * ((a[i] + b[i]) + a3 * (b[i] - a[i])); sum2 = sum2 + func(work); eval_num = eval_num + 1; work[i] = 0.5D * ((a[i] + b[i]) - a3 * (b[i] - a[i])); sum2 = sum2 + func(work); eval_num = eval_num + 1; work[i] = 0.5D * (a[i] + b[i]); } if (1 < dim_num) { a4 = a3; while (true) { for (int i = 0; i < dim_num - 1; i++) { work[i] = 0.5D * ((a[i] + b[i]) + a4 * (b[i] - a[i])); a5 = a3; while (true) { for (int j = i + 1; j < dim_num; j++) { work[j] = 0.5D * ((a[j] + b[j]) + a5 * (b[j] - a[j])); sum3 = sum3 + func(work); eval_num = eval_num + 1; work[j] = 0.5D * (a[j] + b[j]); } a5 = -a5; if (0.0D <= a5) { break; } } work[i] = 0.5D * (a[i] + b[i]); } a4 = -a4; if (0.0D <= a4) { break; } } } result = volume * (sum1 + a1 * sum2 + a2 * sum3); return(result); }
/* Integration Methods */ public static double box_nd(IntegratingFunction func, int dim_num, int order, double[] xtab, double[] weight, out int eval_num) /* * * BOX_ND estimates a multidimensional integral using a product rule. * * Discussion: * * The routine creates a DIM_NUM-dimensional product rule from a 1D rule * supplied by the user. The routine is fairly inflexible. If * you supply a rule for integration from -1 to 1, then your product * box must be a product of DIM_NUM copies of the interval [-1,1]. * * Licensing: * * This code is distributed under the GNU LGPL license. * * Modified: * * 11 September 2006 (translated version in Fortran 90) * 05 Abril 2010 (C#) * * Author (Fortran 90 original version): * * John Burkardt * * Translated to C# by: * * Francisco Heron de Carvalho Junior (MDCC/UFC) * http://www.lia.ufc.br/~heron * * Reference: * * Philip Davis, Philip Rabinowitz, * Methods of Numerical Integration, * Second Edition, * Dover, 2007, * ISBN: 0486453391, * LC: QA299.3.D28. * * Parameters: * * Input, delegate IntegratingFunction, a routine which evaluates * the function to be integrated, of the form: * * double func (double[] x) { * ... * } * * Input, int dim_num, the spatial dimension. * * Input, int order, the number of points used in the 1D rule. * * Input, double[] xtab, the abscissas of the 1D rule (xtab.Length == order). * * Input, double[] weight, the weights of the 1D rule (weigth.Length == order). * * Output, int eval_num, the number of function evaluations. * * Returns: * * double, the approximate value of the integral. * */ { int[] indx = new int[dim_num]; int k; double w; double[] x = new double[dim_num]; eval_num = 0; if (dim_num < 1) { Console.WriteLine("BOX_ND - Fatal error!"); Console.WriteLine("DIM_NUM < 1"); Console.WriteLine(" DIM_NUM = " + dim_num); return(-1); } if (order < 1) { Console.WriteLine("BOX_ND - Fatal error!"); Console.WriteLine(" ORDER < 1"); Console.WriteLine(" ORDER = " + order); return(-1); } k = 0; double result = 0.0D; while (true) { tuple_next(0, order - 1, dim_num, ref k, ref indx); if (k == 0) { break; } // w = product (weight(indx(1:dim_num))) // "product" is a Fortran 90 procedure that mutliplies the elements of a vector. w = 1; foreach (int ix in indx) { w *= weight[ix]; } // x(1:dim_num) = xtab(indx(1:dim_num)) // This Fortran 90 statement is an abbreviation for a iteration over a vector. for (int i = 0; i < dim_num; i++) { x[i] = xtab[indx[i]]; } result = result + w * func(x); eval_num = eval_num + 1; } return(result); }
public static double monte_carlo_nd(IntegratingFunction func, int dim_num, double[] a, double[] b, int eval_num, int seed) /***************************************************************************** * * MONTE_CARLO_ND estimates a multidimensional integral using Monte Carlo. * * Discussion: * * Unlike the other routines, this routine requires the user to specify * the number of function evaluations as an INPUT quantity. * * No attempt at error estimation is made. * * Licensing: * * This code is distributed under the GNU LGPL license. * * Modified: * * 25 February 2007(translated version) * 05 April 2010 (C# version) * * Author (Fortran 90 original version): * * John Burkardt * * Translated to C# by: * * Francisco Heron de Carvalho Junior (MDCC/UFC) * http://www.lia.ufc.br/~heron * * Reference: * * Philip Davis, Philip Rabinowitz, * Methods of Numerical Integration, * Second Edition, * Dover, 2007, * ISBN: 0486453391, * LC: QA299.3.D28. * * Parameters: * * Input, delegate IntegratingFunction, a routine which evaluates * the function to be integrated, of the form: * * double func (double[] x) { * // x.Length == dim_num * ... * } * * Input, int dim_num, the spatial dimension. * * Input, double[] a, b, the integration limits (a.Length == b.Length == dim_num). * * Input, int eval_num, the number of function evaluations. * * Input/output, int seed, a seed for the random number generator. * * Returns: * * double, the approximate value of the integral. * */ { double volume = 1.0D; double[] x = new double[dim_num]; double result = 0.0D; for (int i = 0; i < eval_num; i++) { x = r8vec_uniform_01(dim_num, ref seed); result += func(x); } // volume = product ( b(1:dim_num) - a(1:dim_num)); for (int i = 0; i < dim_num; i++) { volume *= b[i] - a[i]; } result *= volume / eval_num; return(result); }