Example #1
0
    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) + "");
        }
    }
Example #2
0
    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);
    }
Example #3
0
    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);
    }
Example #4
0
    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);
    }
Example #5
0
    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);
    }
Example #6
0
    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);
    }
Example #7
0
    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);
    }
Example #9
0
    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);
    }
Example #10
0
    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);
    }
Example #11
0
    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);
    }
Example #12
0
    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;
        }
    }
Example #13
0
    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]);
            }
        }
    }