コード例 #1
0
    private static void test02()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST02 tests CG_RC with the Wathen matrix.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    13 January 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int    i;
        double rnrm2;

        Console.WriteLine("");
        Console.WriteLine("TEST02");
        Console.WriteLine("  Use CG_RC to solve a linear system");
        Console.WriteLine("  involving the Wathen matrix.");

        const int nx = 5;
        const int ny = 4;

        Console.WriteLine("");
        Console.WriteLine("  NX = " + nx + "");
        Console.WriteLine("  NY = " + ny + "");

        int n = WathenMatrix.wathen_order(nx, ny);

        Console.WriteLine("  N  = " + n + "");

        double[] a = WathenMatrix.wathen(nx, ny, n);

        int seed = 123456789;

        double[] x_exact = UniformRNG.r8vec_uniform_01_new(n, ref seed);

        double[] b = new double[n];
        typeMethods.r8mat_mv(n, n, a, x_exact, ref b);
        //
        //  Here is the initial guess for the solution.
        //
        double[] x = new double[n];
        for (i = 0; i < n; i++)
        {
            x[i] = 0.0;
        }

        double[] ax = new double[n];
        //
        //  Parameters for the stopping test.
        //
        int          it     = 0;
        const int    it_max = 30;
        const double tol    = 1.0E-05;
        double       bnrm2  = 0.0;

        for (i = 0; i < n; i++)
        {
            bnrm2 += b[i] * b[i];
        }

        bnrm2 = Math.Sqrt(bnrm2);
        //
        //  Set parameters for the CG_RC code.
        //
        double[] r   = new double[n];
        double[] z   = new double[n];
        double[] p   = new double[n];
        double[] q   = new double[n];
        int      job = 1;
        //
        //  Repeatedly call the CG_RC code, and on return, do what JOB tells you.
        //
        ConjugateGradientData data = new();

        for (;;)
        {
            job = ConjugateGradientRC.cg_rc(ref data, n, b, ref x, ref r, ref z, ref p, ref q, ref job);
            //
            //  Compute q = A * p.
            //
            if (job == 1)
            {
                typeMethods.r8mat_mv(n, n, a, p, ref q);
            }
            //
            //  Solve M * z = r.
            //
            else if (job == 2)
            {
                for (i = 0; i < n; i++)
                {
                    z[i] = r[i] / a[i + i * n];
                }
            }
            //
            //  Compute r = r - A * x.
            //
            else if (job == 3)
            {
                typeMethods.r8mat_mv(n, n, a, x, ref ax);
                for (i = 0; i < n; i++)
                {
                    r[i] -= ax[i];
                }
            }
            //
            //  Stopping test.
            //
            else if (job == 4)
            {
                rnrm2 = 0.0;
                for (i = 0; i < n; i++)
                {
                    rnrm2 += r[i] * r[i];
                }

                rnrm2 = Math.Sqrt(rnrm2);

                if (bnrm2 == 0.0)
                {
                    if (rnrm2 <= tol)
                    {
                        break;
                    }
                }
                else
                {
                    if (rnrm2 <= tol * bnrm2)
                    {
                        break;
                    }
                }

                it += 1;

                if (it_max <= it)
                {
                    Console.WriteLine("");
                    Console.WriteLine("  Iteration limit exceeded.");
                    Console.WriteLine("  Terminating early.");
                    break;
                }
            }

            job = 2;
        }

        Console.WriteLine("");
        Console.WriteLine("  Number of iterations was " + it + "");
        Console.WriteLine("  Estimated error is " + rnrm2 + "");
        double err = 0.0;

        for (i = 0; i < n; i++)
        {
            double t = Math.Abs(x_exact[i] - x[i]);
            if (err < t)
            {
                err = t;
            }
        }

        Console.WriteLine("  Loo error is " + err + "");

        Console.WriteLine("");
        Console.WriteLine("     I      X(I)         X_EXACT(I)        B(I)");
        Console.WriteLine("");
        for (i = 0; i < n; i++)
        {
            Console.WriteLine("  " + i.ToString(CultureInfo.InvariantCulture).PadLeft(4)
                              + "  " + x[i].ToString(CultureInfo.InvariantCulture).PadLeft(14)
                              + "  " + x_exact[i].ToString(CultureInfo.InvariantCulture).PadLeft(14)
                              + "  " + b[i].ToString(CultureInfo.InvariantCulture).PadLeft(14) + "");
        }
    }
コード例 #2
0
    private static void test03()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST03 carries out test case #3.
    //
    //  Discussion:
    //
    //    Use A3, C3, F3, EXACT3, EXACT_UX3, EXACT_UX3.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    07 July 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int       i;
        int       j;
        const int nx = 5;
        const int ny = 5;

        Console.WriteLine("");
        Console.WriteLine("TEST03");
        Console.WriteLine("  Solve - del ( A del U ) + C U = F ");
        Console.WriteLine("  on the unit square with zero boundary conditions.");
        Console.WriteLine("  A1(X,Y) = 0.0");
        Console.WriteLine("  C1(X,Y) = 1.0");
        Console.WriteLine("  F1(X,Y) = X * ( 1 - X ) * Y * ( 1 - Y )");
        Console.WriteLine("  U1(X,Y) = X * ( 1 - X ) * Y * ( 1 - Y )");
        Console.WriteLine("");
        Console.WriteLine("  This example is contrived so that the system matrix");
        Console.WriteLine("  is the WATHEN matrix.");
        Console.WriteLine("");
        Console.WriteLine("  Number of X grid values NX = " + nx + "");
        Console.WriteLine("  Number of Y grid values NY = " + ny + "");
        //
        //  Geometry definitions.
        //
        const double x_first = 0.0;
        const double x_last  = 1.0;

        double[] x = typeMethods.r8vec_linspace_new(nx, x_first, x_last);

        const double y_first = 0.0;
        const double y_last  = 1.0;

        double[] y = typeMethods.r8vec_linspace_new(ny, y_first, y_last);

        double[] u = FEM_2D_BVP_Serene.fem2d_bvp_serene(nx, ny, a3, c3, f3, x, y, true);

        switch (nx * ny)
        {
        case <= 25:
        {
            Console.WriteLine("");
            Console.WriteLine("     I     J    X         Y               U               Uexact     Error");
            Console.WriteLine("");

            int k = 0;

            for (j = 0; j < ny; j++)
            {
                int inc = (j % 2) switch
                {
                    0 => 1,
                    _ => 2
                };

                for (i = 0; i < nx; i += inc)
                {
                    double uexact = exact3(x[i], y[j]);
                    Console.WriteLine(i.ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                                      + j.ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                                      + x[i].ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                                      + y[j].ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                                      + u[k].ToString(CultureInfo.InvariantCulture).PadLeft(14) + "  "
                                      + uexact.ToString(CultureInfo.InvariantCulture).PadLeft(14) + "  "
                                      + Math.Abs(u[k] - uexact).ToString(CultureInfo.InvariantCulture).PadLeft(14) + "");
                    k += 1;
                }
            }

            break;
        }
        }

        double e1  = FEM_2D_BVP_Serene.fem2d_l1_error_serene(nx, ny, x, y, u, exact3);
        double e2  = FEM_2D_BVP_Serene.fem2d_l2_error_serene(nx, ny, x, y, u, exact3);
        double h1s = FEM_2D_BVP_Serene.fem2d_h1s_error_serene(nx, ny, x, y, u, exact_ux3, exact_uy3);

        Console.WriteLine("");
        Console.WriteLine("  l1 norm of error  = " + e1 + "");
        Console.WriteLine("  L2 norm of error  = " + e2 + "");
        Console.WriteLine("  Seminorm of error = " + h1s + "");

        //
        //  Pull out the Wathen matrix from MATLAB.
        //  It will have been multiplied by a random scale factor.
        //  While my numbering scheme is
        //    3  2  1
        //    4     8
        //    5  6  7
        //  the numbering scheme used here is
        //    1  2  3
        //    4     5
        //    6  7  8
        //
        double[] amat = WathenMatrix.wathen(1, 1, 8);

        double scale = 0.5 * amat[0 + 2 * 8];

        for (j = 0; j < 8; j++)
        {
            for (i = 0; i < 8; i++)
            {
                amat[i + j * 8] /= scale;
            }
        }

        typeMethods.r8mat_print(8, 8, amat, "  Wathen matrix:");
    }