private static void legendre_set_test() //****************************************************************************80 // // Purpose: // // LEGENDRE_SET_TEST tests LEGENDRE_SET. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 November 2014 // // Author: // // John Burkardt // { Console.WriteLine(""); Console.WriteLine("LEGENDRE_SET_TEST"); Console.WriteLine(" LEGENDRE_SET returns points and weights of"); Console.WriteLine(" Gauss-Legendre quadrature rules."); Console.WriteLine(""); Console.WriteLine(" N 1 X^4 Runge"); Console.WriteLine(""); for (int n = 1; n <= 10; n++) { double[] x = new double[n]; double[] w = new double[n]; LegendreQuadrature.legendre_set(n, ref x, ref w); double e1 = 0.0; double e2 = 0.0; double e3 = 0.0; for (int i = 0; i < n; i++) { e1 += w[i]; e2 += w[i] * Math.Pow(x[i], 4); e3 += w[i] / (1.0 + 25.0 * x[i] * x[i]); } Console.WriteLine(" " + n.ToString(CultureInfo.InvariantCulture).PadLeft(2) + " " + e1.ToString(CultureInfo.InvariantCulture).PadLeft(14) + " " + e2.ToString(CultureInfo.InvariantCulture).PadLeft(14) + " " + e3.ToString(CultureInfo.InvariantCulture).PadLeft(14) + ""); } }
public static double ball_unit_15_3d(int setting, Func <int, double, double, double, double> func) //****************************************************************************80 // // Purpose: // // BALL_UNIT_15_3D approximates an integral inside the unit ball in 3D. // // Integration region: // // X * X + Y * Y + Z * Z <= 1. // // Discussion: // // A 512 point 15-th degree formula is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 October 2000 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, double FUNC ( double x, double y, double z ), the name of the // user supplied function which evaluates F(X,Y,Z). // // Output, double BALL_UNIT_15_3D, the approximate integral of the function. // { int i; const int order1 = 4; const int order2 = 8; double[] weight1 = { 0.0328402599, 0.0980481327, 0.1262636728, 0.0761812678 }; double[] xtab1 = { 0.3242534234, 0.6133714327, 0.8360311073, 0.9681602395 }; double[] xtab2 = new double[order2]; double[] weight2 = new double[order2]; LegendreQuadrature.legendre_set(order2, ref xtab2, ref weight2); const double w = 3.0 / 32.0; double quad = 0.0; for (i = 0; i < order1; i++) { int j; for (j = 0; j < order2; j++) { double sj = xtab2[j]; double cj = Math.Sqrt(1.0 - sj * sj); int k; for (k = 1; k <= 16; k++) { double sk = Math.Sin(k * Math.PI / 8.0); double ck = Math.Cos(k * Math.PI / 8.0); double x = xtab1[i] * cj * ck; double y = xtab1[i] * cj * sk; double z = xtab1[i] * sj; quad += w * weight1[i] * weight2[j] * func(setting, x, y, z); } } } double volume = ball_unit_volume_3d(); double result = quad * volume; return(result); }
public static double ball_unit_07_3d(int setting, Func <int, double, double, double, double> func) //****************************************************************************80 // // Purpose: // // BALL_UNIT_07_3D approximates an integral inside the unit ball in 3D. // // Integration region: // // X*X + Y*Y + Z*Z <= 1. // // Discussion: // // A 64 point 7-th degree formula is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, double FUNC ( double x, double y, double z ), the name of // the user supplied function which evaluates F(X,Y,Z). // // Output, double BALL_UNIT_07_3D, the approximate integral of the function. // { const int order = 4; int i; int j; double[] weight1 = { 0.19455533421780251826, 0.13877799911553081506, 0.13877799911553081506, 0.19455533421780251826 }; double[] weight2 = new double[4]; double[] weight3 = new double[4]; double[] xtab1 = { -0.906179845938663992797626878299, -0.538469310105683091036314420700, 0.538469310105683091036314420700, 0.906179845938663992797626878299 }; double[] xtab2 = new double[4]; double[] xtab3 = new double[4]; // // Set XTAB2 and WEIGHT2. // for (j = 0; j < order; j++) { double angle = Math.PI * (2 * j - 1) / (2 * order); xtab2[j] = Math.Cos(angle); } for (j = 0; j < order; j++) { weight2[j] = 1.0; } // // Set XTAB3 and WEIGHT3 for the interval [-1,1]. // LegendreQuadrature.legendre_set(order, ref xtab3, ref weight3); const double w = 3.0 / 16.0; double quad = 0.0; for (i = 0; i < order; i++) { for (j = 0; j < order; j++) { int k; for (k = 0; k < order; k++) { double x = xtab1[i] * Math.Sqrt(1.0 - xtab2[j] * xtab2[j]) * Math.Sqrt(1.0 - xtab3[k] * xtab3[k]); double y = xtab1[i] * xtab2[j] * Math.Sqrt(1.0 - xtab3[k] * xtab3[k]); double z = xtab1[i] * xtab3[k]; quad += w * weight1[i] * weight2[j] * weight3[k] * func(setting, x, y, z); } } } double volume = ball_unit_volume_3d(); double result = quad * volume; return(result); }
public static double torus_square_14c(int setting, Func <int, double, double, double, double> func, double r1, double r2) //****************************************************************************80 // // Purpose: // // TORUS_SQUARE_14C approximates an integral in a "square" torus in 3D. // // Discussion: // // A 14-th degree 960 point formula is used. // // Integration region: // // R1 - R2 <= Math.Sqrt ( X*X + Y*Y ) <= R1 + R2, // and // -R2 <= Z <= R2. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, Func< double, double, double, double > func, the name of the // user supplied function to be integrated. // // Input, double R1, R2, the radii that define the torus. // // Output, double RESULT, the approximate integral of the function. // { int n; const int order = 8; double[] rtab = new double[order]; double[] weight = new double[order]; LegendreQuadrature.legendre_set(order, ref rtab, ref weight); double w = 1.0 / (60.0 * r1); double quad = 0.0; for (n = 1; n <= 15; n++) { double angle = 2.0 * Math.PI * n / 15.0; double cth = Math.Cos(angle); double sth = Math.Sin(angle); int i; for (i = 0; i < order; i++) { double u = r1 + rtab[i] * r2; double x = u * cth; double y = u * sth; int j; for (j = 0; j < order; j++) { double z = rtab[j] * r2; quad += u * w * weight[i] * weight[j] * func(setting, x, y, z); } } } double volume = torus_square_volume_3d(r1, r2); double result = quad * volume; return(result); }
public static double tetra_tproduct(int setting, Func <int, double, double, double, double> func, int order, double[] x, double[] y, double[] z) //****************************************************************************80 // // Purpose: // // TETRA_TPRODUCT approximates an integral in a tetrahedron in 3D. // // Discussion: // // Integration is carried out over the points inside an arbitrary // tetrahedron whose four vertices are given. // // An ORDER**3 point (2*ORDER-1)-th degree triangular product // Gauss-Legendre rule is used. // // With ORDER = 8, this routine is equivalent to the routine TETR15 // in the reference, page 367. // // Thanks to Joerg Behrens, [email protected], for numerous suggestions // and corrections. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 20 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, Func< double, double, double, double > func, the name of the // user supplied function to be integrated. // // Input, int ORDER, the order of the basic quadrature rules. // ORDER should be between 1 and 9. // // Input, double X[4], Y[4], Z[4], the vertices // of the tetrahedron. // // Output, double TETRA_TPRODUCT, the approximate integral of the function. // { int i; int k; switch (order) { case < 1: case > 9: Console.WriteLine(""); Console.WriteLine("TETRA_TPRODUCT - Fatal error!"); Console.WriteLine(" The quadrature rule orders must be between 1 and 9."); Console.WriteLine(" The input value was ORDER = " + order + ""); return(1); } // // Get the Gauss-Legendre ORDER point rules on [-1,1] for integrating // F(X), // X * F(X), // X * X * F(X). // double[] xtab0 = new double[order]; double[] xtab1 = new double[order]; double[] xtab2 = new double[order]; double[] weight0 = new double[order]; double[] weight1 = new double[order]; double[] weight2 = new double[order]; LegendreQuadrature.legendre_set(order, ref xtab0, ref weight0); LegendreQuadrature.legendre_set_x1(order, ref xtab1, ref weight1); LegendreQuadrature.legendre_set_x2(order, ref xtab2, ref weight2); // // Adjust the rules from [-1,1] to [0,1]. // const double a = -1.0; const double b = +1.0; const double c = 0.0; const double d = 1.0; QuadratureRule.rule_adjust(a, b, c, d, order, ref xtab0, ref weight0); QuadratureRule.rule_adjust(a, b, c, d, order, ref xtab1, ref weight1); QuadratureRule.rule_adjust(a, b, c, d, order, ref xtab2, ref weight2); // // For rules with a weight function that is not 1, the weight vectors // require further adjustment. // for (i = 0; i < order; i++) { weight1[i] /= 2.0; } for (i = 0; i < order; i++) { weight2[i] /= 4.0; } // // Carry out the quadrature. // double quad = 0.0; for (k = 0; k < order; k++) { int j; for (j = 0; j < order; j++) { for (i = 0; i < order; i++) { double xval = x[0] + (((x[3] - x[2]) * xtab0[i] + (x[2] - x[1])) * xtab1[j] + (x[1] - x[0])) * xtab2[k]; double yval = y[0] + (((y[3] - y[2]) * xtab0[i] + (y[2] - y[1])) * xtab1[j] + (y[1] - y[0])) * xtab2[k]; double zval = z[0] + (((z[3] - z[2]) * xtab0[i] + (z[2] - z[1])) * xtab1[j] + (z[1] - z[0])) * xtab2[k]; quad += 6.0 * weight0[i] * weight1[j] * weight2[k] * func(setting, xval, yval, zval); } } } // // Compute the volume of the tetrahedron. // double volume = tetra_volume(x, y, z); double result = quad * volume; return(result); }
public static double tetra_07(int setting, Func <int, double, double, double, double> func, double[] x, double[] y, double[] z) //****************************************************************************80 // // Purpose: // // TETRA_07 approximates an integral inside a tetrahedron in 3D. // // Integration region: // // Points inside a tetrahedron whose four corners are given. // // Discussion: // // A 64 point 7-th degree conical product Gauss formula is used, // Stroud number T3:7-1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Arthur Stroud, Don Secrest, // Gaussian Quadrature Formulas, // Prentice Hall, 1966, pages 42-43, // LC: QA299.4G3S7 // // Parameters: // // Input, Func< double, double, double, double > func, the name of the // user supplied function to be integrated. // // Input, double X[4], Y[4], Z[4], the coordinates of // the vertices. // // Output, double TETRAQ_07, the approximate integral of the function. // { int i; const int order = 4; double[] weight1 = new double[4]; double[] weight2 = { 0.1355069134, 0.2034645680, 0.1298475476, 0.0311809709 }; double[] weight3 = { 0.1108884156, 0.1434587898, 0.0686338872, 0.0103522407 }; double[] xtab1 = new double[4]; double[] xtab2 = { 0.0571041961, 0.2768430136, 0.5835904324, 0.8602401357 }; double[] xtab3 = { 0.0485005495, 0.2386007376, 0.5170472951, 0.7958514179 }; // // Get the Gauss-Legendre weights and abscissas for [-1,1]. // LegendreQuadrature.legendre_set(order, ref xtab1, ref weight1); // // Adjust the rule for the interval [0,1]. // const double a = -1.0; const double b = +1.0; const double c = 0.0; const double d = 1.0; QuadratureRule.rule_adjust(a, b, c, d, order, ref xtab1, ref weight1); // // Carry out the quadrature. // double quad = 0.0; for (i = 0; i < order; i++) { int j; for (j = 0; j < order; j++) { int k; for (k = 0; k < order; k++) { // // Compute the barycentric coordinates of the point in the unit triangle. // double t = xtab3[k]; double u = xtab2[j] * (1.0 - xtab3[k]); double v = xtab1[i] * (1.0 - xtab2[j]) * (1.0 - xtab3[k]); double w = 1.0 - t - u - v; // // Compute the corresponding point in the triangle. // double xval = t * x[0] + u * x[1] + v * x[2] + w * x[3]; double yval = t * y[0] + u * y[1] + v * y[2] + w * y[3]; double zval = t * z[0] + u * z[1] + v * z[2] + w * z[3]; quad += 6.0 * weight1[i] * weight2[j] * weight3[k] * func(setting, xval, yval, zval); } } } double volume = tetra_volume(x, y, z); double result = quad * volume; return(result); }
public static double lens_half_2d(Func <double, double, double> func, double[] center, double r, double theta1, double theta2, int order) //****************************************************************************80 // // Purpose: // // LENS_HALF_2D approximates an integral in a circular half lens in 2D. // // Discussion: // // A circular half lens is formed by drawing a circular arc, // and joining its endpoints. // // This rule for a circular half lens simply views the region as // a product region, with a coordinate "S" that varies along the // radial direction, and a coordinate "T" that varies in the perpendicular // direction, and whose extent varies as a function of S. // // A Gauss-Legendre rule is used to construct a product rule that is // applied to the region. The accuracy of the Gauss-Legendre rule, // which is valid for a rectangular product rule region, does not // apply straightforwardly to this region, since the limits in the // "T" coordinate are being handled implicitly. // // This is simply an application of the QMULT_2D algorithm of Stroud. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 14 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, Func < double, double, double > func, the name of the // user supplied function to be integrated. // // Input, double[] center, the center of the circle. // // Input, double R, the radius of the circle. // // Input, double THETA1, THETA2, the angles of the rays // that begin and end the arc. // // Input, int ORDER, the order of the Gauss-Legendre rule // to be used. Legal values include 1 through 20, 32 or 64. // // Output, double LENS_HALF_2D, the approximate value // of the integral of the function over the half lens. // { int i; double quad; // // Determine the points A (on the secant) and B (on the circumference) // that will form the "S" direction. // double ax = center[0] + r * 0.5 * (Math.Cos(theta1) + Math.Cos(theta2)); double ay = center[1] + r * 0.5 * (Math.Sin(theta1) + Math.Sin(theta2)); double bx = center[0] + r * Math.Cos(0.5 * (theta1 + theta2)); double by = center[1] + r * Math.Sin(0.5 * (theta1 + theta2)); // // Find the length of the line between A and B. // double s_length = Math.Sqrt(Math.Pow(ax - bx, 2) + Math.Pow(ay - by, 2)); switch (s_length) { case 0.0: quad = 0.0; return(quad); } // // Retrieve the Legendre rule of the given order. // double[] xtab = new double[order]; double[] weight = new double[order]; LegendreQuadrature.legendre_set(order, ref xtab, ref weight); // // Determine the unit vector in the T direction. // double tdirx = (ay - by) / s_length; double tdiry = (bx - ax) / s_length; quad = 0.0; for (i = 0; i < order; i++) { double w1 = 0.5 * s_length * weight[i]; // // Map the quadrature point to an S coordinate. // double sx = ((1.0 - xtab[i]) * ax + (1.0 + xtab[i]) * bx) / 2.0; double sy = ((1.0 - xtab[i]) * ay + (1.0 + xtab[i]) * by) / 2.0; // // Determine the length of the line in the T direction, from the // S axis to the circle circumference. // double thi = Math.Sqrt((r - 0.25 * (1.0 - xtab[i]) * s_length) * (1.0 - xtab[i]) * s_length); // // Determine the maximum and minimum T coordinates by going // up and down in the T direction from the S axis. // double cx = sx + tdirx * thi; double cy = sy + tdiry * thi; double dx = sx - tdirx * thi; double dy = sy - tdiry * thi; // // Find the length of the T direction. // double t_length = Math.Sqrt(Math.Pow(cx - dx, 2) + Math.Pow(cy - dy, 2)); int j; for (j = 0; j < order; j++) { double w2 = 0.5 * t_length * weight[j]; // // Map the quadrature point to a T coordinate. // double tx = ((1.0 - xtab[j]) * cx + (1.0 + xtab[j]) * dx) / 2.0; double ty = ((1.0 - xtab[j]) * cy + (1.0 + xtab[j]) * dy) / 2.0; quad += w1 * w2 * func(tx, ty); } } return(quad); }
public static double cpv(Func <double, double> f, double a, double b, int n) //****************************************************************************80 // // Purpose: // // CPV estimates the Cauchy Principal Value of an integral. // // Location: // // http://people.sc.fsu.edu/~jburkardt/c_src/cauchy_principal_value/cauchy_principal_value.cpp // // Discussion: // // This function can be used to estimate the Cauchy Principal Value of // a singular integral of the form // Integral f(t)/(t-x) dt // over an interval which includes the singularity point t=x. // // Isolate the singularity at x in a symmetric interval of finite size delta: // // CPV ( Integral ( a <= t <= b ) p(t) / ( t - x ) dt ) // = Integral ( a <= t <= x - delta ) p(t) / ( t - x ) dt // + CPV ( Integral ( x - delta <= t <= x + delta ) p(t) / ( t - x ) dt ) // + Integral ( x + delta <= t <= b ) p(t) / ( t - x ) dt. // // We assume the first and third integrals can be handled in the usual way. // The second integral can be rewritten as // Integral ( -1 <= s <= +1 ) ( p(s*delta+x) - p(x) ) / s ds // and approximated by // Sum ( 1 <= i <= N ) w(i) * ( p(xi*delta+x) - p(x) ) / xi(i) // = Sum ( 1 <= i <= N ) w(i) * ( p(xi*delta+x) ) / xi(i) // if we assume that N is even, so that coefficients of p(x) sum to zero. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 April 2015 // // Author: // // John Burkardt // // Reference: // // Julian Noble, // Gauss-Legendre Principal Value Integration, // Computing in Science and Engineering, // Volume 2, Number 1, January-February 2000, pages 92-95. // // Parameters: // // Input, double F ( double x ), the function that evaluates the // integrand. // // Input, double A, B, the endpoints of the symmetric interval, // which contains a singularity of the form 1/(X-(A+B)/2). // // Input, int N, the number of Gauss points to use. // N must be even. // // Output, double CPV, the estimate for the Cauchy Principal Value. // { int i; // // N must be even. // if (n % 2 != 0) { Console.WriteLine(""); Console.WriteLine("CPV - Fatal error!"); Console.WriteLine(" N must be even."); return(1); } // // Get the Gauss-Legendre rule. // double[] x = new double[n]; double[] w = new double[n]; LegendreQuadrature.legendre_set(n, ref x, ref w); // // Estimate the integral. // double value = 0.0; for (i = 0; i < n; i++) { double x2 = ((1.0 - x[i]) * a + (1.0 + x[i]) * b) / 2.0; value += w[i] * f(x2) / x[i]; } return(value); }
public static double qmult_2d(Func <double, double, double> func, double a, double b, Func <double, double> fup, Func <double, double> flo) //****************************************************************************80 // // Purpose: // // QMULT_2D approximates an integral with varying Y dimension in 2D. // // Integration region: // // A <= X <= B // // and // // FLO(X) <= Y <= FHI(X). // // Discussion: // // A 256 point product of two 16 point 31-st degree Gauss-Legendre // quadrature formulas is used. // // This routine could easily be modified to use a different // order product rule by changing the value of ORDER. // // Another easy change would allow the X and Y directions to // use quadrature rules of different orders. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, Func < double, double, double > func, the name of the // user supplied function which evaluates F(X,Y). // // Input, double A, B, the lower and upper limits of X integration. // // Input, double FUP ( double x ), double FLO ( double x ), // the names of the user supplied functions which evaluate the upper // and lower limits of the Y integration. // { int i; const int order = 16; double[] xtab = new double[order]; double[] weight = new double[order]; LegendreQuadrature.legendre_set(order, ref xtab, ref weight); double quad = 0.0; for (i = 0; i < order; i++) { double w1 = 0.5 * (b - a) * weight[i]; double x = 0.5 * (b - a) * xtab[i] + 0.5 * (b + a); double c = flo(x); double d = fup(x); int j; for (j = 0; j < order; j++) { double w2 = 0.5 * (d - c) * weight[j]; double y = 0.5 * (d - c) * xtab[j] + 0.5 * (d + c); quad += w1 * w2 * func(x, y); } } return(quad); }
public static double qmult_1d(int setting, Func <int, double, double> func, double a, double b) //****************************************************************************80 // // Purpose: // // QMULT_1D approximates an integral over an interval in 1D. // // Integration region: // // A <= X <= B. // // Discussion: // // A 16 point 31-st degree Gauss-Legendre formula is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, double FUNC ( double x ), the name of the user supplied // function which evaluates F(X). // // Input, double A, B, the lower and upper limits of integration. // // Output, double QMULT_1D, the approximate integral of // the function. // { int i; const int order = 16; double[] xtab = new double[order]; double[] weight = new double[order]; LegendreQuadrature.legendre_set(order, ref xtab, ref weight); double quad = 0.0; for (i = 0; i < order; i++) { double x = 0.5 * (b - a) * xtab[i] + 0.5 * (a + b); quad += 0.5 * weight[i] * func(setting, x); } double volume = b - a; double result = quad * volume; return(result); }
public static double qmult_3d(int settings, Func <int, double, double, double, double> func, double a, double b, Func <double, double> fup1, Func <double, double> flo1, Func <double, double, double> fup2, Func <double, double, double> flo2) //****************************************************************************80 // // Purpose: // // QMULT_3D approximates an integral with varying Y and Z dimension in 3D. // // Integration region: // // A <= X <= B, // and // FLO(X) <= Y <= FHI(X), // and // FLO2(X,Y) <= Z <= FHI2(X,Y). // // Discussion: // // A 4096 point product of three 16 point 31-st degree Gauss-Legendre // quadrature formulas is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 March 2008 // // Author: // // John Burkardt // // Reference: // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, Func< double, double, double, double > func, the name of the // user supplied unction which evaluates F(X,Y,Z). // // Input, double A, B, the lower and upper limits of X integration. // // Input, double FUP1 ( double x ), double FLO1 ( double x ), the names // of the user supplied functions which evaluate the upper and lower // limits of the Y integration. // // Input, double FUP2 ( double x, double y ), // double FLO2 ( double x, double y ), the names of the user // supplied functions which evaluate the upper and lower // limits of the Z integration. // // Output, double QMULT_3D, the approximate integral of // the function. // { int i; const int order = 16; double[] xtab = new double[order]; double[] weight = new double[order]; LegendreQuadrature.legendre_set(order, ref xtab, ref weight); double quad = 0.0; for (i = 0; i < order; i++) { double x = 0.5 * (b - a) * xtab[i] + 0.5 * (b + a); double w1 = 0.5 * weight[i]; double c = flo1(x); double d = fup1(x); int j; for (j = 0; j < order; j++) { double w2 = 0.5 * (d - c) * weight[j]; double y = 0.5 * (d - c) * xtab[j] + 0.5 * (d + c); double e = flo2(x, y); double f = fup2(x, y); int k; for (k = 0; k < order; k++) { double w3 = 0.5 * (f - e) * weight[k]; double z = 0.5 * (f - e) * xtab[k] + 0.5 * (f + e); quad += w1 * w2 * w3 * func(settings, x, y, z); } } } double volume = b - a; double result = quad * volume; return(result); }
public static void square_unit_set(int rule, int order, double[] xtab, double[] ytab, double[] weight) //****************************************************************************80 // // Purpose: // // SQUARE_UNIT_SET sets quadrature weights and abscissas in the unit square. // // Discussion; // // To get the value of ORDER associated with a given rule, // call SQUARE_UNIT_SIZE first. // // Integration region: // // -1 <= X <= 1, // and // -1 <= Y <= 1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 23 March 2008 // // Author: // // John Burkardt // // Reference: // // Gilbert Strang, George Fix, // An Analysis of the Finite Element Method, // Cambridge, 1973, // ISBN: 096140888X, // LC: TA335.S77. // // Arthur Stroud, // Approximate Calculation of Multiple Integrals, // Prentice Hall, 1971, // ISBN: 0130438936, // LC: QA311.S85. // // Parameters: // // Input, int RULE, the rule number. // 1, order 1, degree 1 rule. // 2, order 4, degree 3, rule. // 3, order 9, degree 5 rule. // 4, order 12 degree 7 rule, Stroud number C2:7-1. // 5, order 13 degree 7 rule, Stroud number C2:7-3. // 6, order 64 degree 15 product rule. // // Input, int ORDER, the order of the rule. // // Output, double XTAB[ORDER], YTAB[ORDER], the abscissas. // // Output, double WEIGHT[ORDER], the weights. // { double c; const int order2 = 8; double r; double s; double t; double w1; double w2; double w3; double z; switch (rule) { case 1: weight[0] = 4.0; xtab[0] = 0.0; ytab[0] = 0.0; break; case 2: const double a = 1.0; s = 1.0 / Math.Sqrt(3.0); xtab[0] = -s; xtab[1] = s; xtab[2] = -s; xtab[3] = s; ytab[0] = -s; ytab[1] = -s; ytab[2] = s; ytab[3] = s; weight[0] = a; weight[1] = a; weight[2] = a; weight[3] = a; break; case 3: s = Math.Sqrt(0.6); z = 0.0; w1 = 64.0 / 81.0; w2 = 25.0 / 81.0; w3 = 40.0 / 81.0; xtab[0] = z; xtab[1] = -s; xtab[2] = s; xtab[3] = -s; xtab[4] = s; xtab[5] = z; xtab[6] = -s; xtab[7] = s; xtab[8] = z; ytab[0] = z; ytab[1] = -s; ytab[2] = -s; ytab[3] = s; ytab[4] = s; ytab[5] = -s; ytab[6] = z; ytab[7] = z; ytab[8] = s; weight[0] = w1; weight[1] = w2; weight[2] = w2; weight[3] = w2; weight[4] = w2; weight[5] = w3; weight[6] = w3; weight[7] = w3; weight[8] = w3; break; case 4: r = Math.Sqrt(6.0 / 7.0); c = 3.0 * Math.Sqrt(583.0); s = Math.Sqrt((114.0 - c) / 287.0); t = Math.Sqrt((114.0 + c) / 287.0); w1 = 4.0 * 49.0 / 810.0; w2 = 4.0 * (178981.0 + 923.0 * c) / 1888920.0; w3 = 4.0 * (178981.0 - 923.0 * c) / 1888920.0; z = 0.0; xtab[0] = r; xtab[1] = z; xtab[2] = -r; xtab[3] = z; xtab[4] = s; xtab[5] = -s; xtab[6] = -s; xtab[7] = s; xtab[8] = t; xtab[9] = -t; xtab[10] = -t; xtab[11] = t; ytab[0] = z; ytab[1] = r; ytab[2] = z; ytab[3] = -r; ytab[4] = s; ytab[5] = s; ytab[6] = -s; ytab[7] = -s; ytab[8] = t; ytab[9] = t; ytab[10] = -t; ytab[11] = -t; weight[0] = w1; weight[1] = w1; weight[2] = w1; weight[3] = w1; weight[4] = w2; weight[5] = w2; weight[6] = w2; weight[7] = w2; weight[8] = w3; weight[9] = w3; weight[10] = w3; weight[11] = w3; break; case 5: r = Math.Sqrt(12.0 / 35.0); c = 3.0 * Math.Sqrt(186.0); s = Math.Sqrt((93.0 + c) / 155.0); t = Math.Sqrt((93.0 - c) / 155.0); w1 = 8.0 / 162.0; w2 = 98.0 / 162.0; w3 = 31.0 / 162.0; z = 0.0; xtab[0] = z; xtab[1] = r; xtab[2] = -r; xtab[3] = z; xtab[4] = z; xtab[5] = s; xtab[6] = s; xtab[7] = -s; xtab[8] = -s; xtab[9] = t; xtab[10] = t; xtab[11] = -t; xtab[12] = -t; ytab[0] = z; ytab[1] = z; ytab[2] = z; ytab[3] = r; ytab[4] = -r; ytab[5] = t; ytab[6] = -t; ytab[7] = t; ytab[8] = -t; ytab[9] = s; ytab[10] = -s; ytab[11] = s; ytab[12] = -s; weight[0] = w1; weight[1] = w2; weight[2] = w2; weight[3] = w2; weight[4] = w2; weight[5] = w3; weight[6] = w3; weight[7] = w3; weight[8] = w3; weight[9] = w3; weight[10] = w3; weight[11] = w3; weight[12] = w3; break; case 6: { double[] xtab2 = new double[order2]; double[] weight2 = new double[order2]; LegendreQuadrature.legendre_set(order2, ref xtab2, ref weight2); int k = 0; int i; for (i = 0; i < order2; i++) { int j; for (j = 0; j < order2; j++) { xtab[k] = xtab2[i]; ytab[k] = xtab2[j]; weight[k] = weight2[i] * weight2[j]; k += 1; } } break; } default: Console.WriteLine(""); Console.WriteLine("SQUARE_UNIT_SET - Fatal error!"); Console.WriteLine(" Illegal value of RULE = " + rule + ""); break; } }
public static void fem1d_lagrange_stiffness(int x_num, double[] x, int q_num, Func <double, double> f, ref double[] a, ref double[] m, ref double[] b) //****************************************************************************80 // // Purpose: // // FEM1D_LAGRANGE_STIFFNESS evaluates the Lagrange polynomial stiffness matrix. // // Discussion: // // The finite element method is to be applied over a given interval that // has been meshed with X_NUM points X. // // The finite element basis functions are to be the X_NUM Lagrange // basis polynomials L(i)(X), such that // L(i)(X(j)) = delta(i,j). // // The following items are computed: // * A, the stiffness matrix, with A(I,J) = integral L'(i)(x) L'(j)(x) // * M, the mass matrix, with M(I,J) = integral L(i)(x) L(j)(x) // * B, the load matrix, with B(I) = integral L(i)(x) F(x) // // The integrals are approximated by quadrature. // // Boundary conditions are not handled by this routine. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 November 2014 // // Author: // // John Burkardt // // Parameters: // // Input, int X_NUM, the number of nodes. // // Input, double X[X_NUM], the coordinates of the nodes. // // Input, int Q_NUM, the number of quadrature points to use. // // Input, double F ( double X ), the right hand side function. // // Output, double A[X_NUM*X_NUM], the stiffness matrix. // // Output, double M[X_NUM*X_NUM], the mass matrix. // // Output, double B[X_NUM], the right hand side vector. // { // // Get the quadrature rule for [-1,+1]. // double[] q_x = new double[q_num]; double[] q_w = new double[q_num]; LegendreQuadrature.legendre_set(q_num, ref q_x, ref q_w); // // Adjust the quadrature rule to the interval [ x(1), x(x_num) } // for (int q_i = 0; q_i < q_num; q_i++) { q_x[q_i] = ((1.0 - q_x[q_i]) * x[0] + (1.0 + q_x[q_i]) * x[x_num - 1]) / 2.0; q_w[q_i] = q_w[q_i] * (x[x_num - 1] - x[0]) / 2.0; } // // Evaluate all the Lagrange basis polynomials at all the quadrature points. // double[] l = lagrange_value(x_num, x, q_num, q_x); // // Evaluate all the Lagrange basis polynomial derivatives at all // the quadrature points. // double[] lp = lagrange_derivative(x_num, x, q_num, q_x); // // Assemble the matrix and right hand side. // for (int x_j = 0; x_j < x_num; x_j++) { for (int x_i = 0; x_i < x_num; x_i++) { a[x_i + x_j * x_num] = 0.0; m[x_i + x_j * x_num] = 0.0; } b[x_j] = 0.0; } for (int x_i = 0; x_i < x_num; x_i++) { for (int q_i = 0; q_i < q_num; q_i++) { double li = l[q_i + x_i * q_num]; double lpi = lp[q_i + x_i * q_num]; for (int x_j = 0; x_j < x_num; x_j++) { double lj = l[q_i + x_j * q_num]; double lpj = lp[q_i + x_j * q_num]; a[x_i + x_j * x_num] += q_w[q_i] * lpi * lpj; m[x_i + x_j * x_num] += q_w[q_i] * li * lj; } b[x_i] += q_w[q_i] * li *f(q_x[q_i]); } } }