Пример #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 test01()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST01 uses CG_RC for the simple 1, -2, 1 matrix.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    13 January 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int       i;
        const int n = 21;
        double    rnrm2;

        Console.WriteLine("");
        Console.WriteLine("TEST01");
        Console.WriteLine("  Use CG_RC on the 1, -2, 1 matrix.");
        //
        //  In order to specify the right hand side, pick an exact solution,
        //  and multiply by the matrix.
        //
        double[] x_exact = new double[n];
        for (i = 0; i < n; i++)
        {
            double angle = 2.0 * Math.PI * i / (n - 1);
            x_exact[i] = Math.Sin(angle);
        }

        double[] b = new double[n];

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

        for (i = 0; i < n - 1; i++)
        {
            b[i] += x_exact[i + 1];
        }

        for (i = 1; i < n; i++)
        {
            b[i] += x_exact[i - 1];
        }

        //
        //  Here is the initial guess for the solution.
        //
        double[] x = new double[n];
        for (i = 0; i < n; i++)
        {
            x[i] = 0.0;
        }

        //
        //  Parameters for the stopping test.
        //
        int    it     = 0;
        int    it_max = 30;
        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)
            {
                for (i = 0; i < n; i++)
                {
                    q[i] = -2.0 * p[i];
                }

                for (i = 0; i < n - 1; i++)
                {
                    q[i] += p[i + 1];
                }

                for (i = 1; i < n; i++)
                {
                    q[i] += p[i - 1];
                }
            }
            //
            //  Solve M * z = r.
            //
            else if (job == 2)
            {
                for (i = 0; i < n; i++)
                {
                    z[i] = r[i] / -2.0;
                }
            }
            //
            //  Compute r = r - A * x.
            //
            else if (job == 3)
            {
                for (i = 0; i < n; i++)
                {
                    r[i] += 2.0 * x[i];
                }

                for (i = 0; i < n - 1; i++)
                {
                    r[i] -= x[i + 1];
                }

                for (i = 1; i < n; i++)
                {
                    r[i] -= x[i - 1];
                }
            }
            //
            //  Stopping test on R.
            //
            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) + "");
        }
    }
    public static double[] solve_cg(int n, int[] diag, int nz_num, int[] ia, int[] ja,
                                    double[] a, double[] b)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    SOLVE_CG solves a linear system using the conjugate gradient method.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    25 January 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int N, the number of nodes.
    //
    //    Input, int DIAG[N], contains for each index 0 <= I < N, the unique
    //    index J such that IA[J] = JA[J] = I.
    //
    //    Input, int NZ_NUM, the number of nonzero entries.
    //
    //    Input, int IA[NZ_NUM], JA[NZ_NUM], the row and column
    //    indices of the nonzero entries.
    //
    //    Input, double A[NZ_NUM], the nonzero entries of the matrix.
    //
    //    Input, double B[N], the right hand side.
    //
    //    Output, double SOLVE_CG[N], the solution of the linear system.
    //
    {
        double aii;
        int    i;
        double rnrm2;
        ConjugateGradientData data = new();

        int          it     = 0;
        const int    it_max = 100;
        const double tol    = 1.0E-08;
        double       bnrm2  = 0.0;

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

        bnrm2 = Math.Sqrt(bnrm2);

        double[] p = new double[n];
        double[] q = new double[n];
        double[] r = new double[n];
        double[] x = new double[n];
        double[] z = new double[n];

        for (i = 0; i < n; i++)
        {
            aii  = a[diag[i]];
            x[i] = b[i] / aii;
        }

        Console.WriteLine("");
        Console.WriteLine("  Step        Residual");
        Console.WriteLine("");

        int job = 1;

        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.
            //
            int k;
            int j;
            if (job == 1)
            {
                for (i = 0; i < n; i++)
                {
                    q[i] = 0.0;
                }

                for (k = 0; k < nz_num; k++)
                {
                    i     = ia[k] - 1;
                    j     = ja[k] - 1;
                    q[i] += a[k] * p[j];
                }
            }
            //
            //  Solve M * z = r.
            //
            else if (job == 2)
            {
                for (i = 0; i < n; i++)
                {
                    aii  = a[diag[i]];
                    z[i] = r[i] / aii;
                }
            }
            //
            //  Compute r = r - A * x.
            //
            else if (job == 3)
            {
                for (k = 0; k < nz_num; k++)
                {
                    i     = ia[k] - 1;
                    j     = ja[k] - 1;
                    r[i] -= a[k] * x[j];
                }
            }
            //
            //  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;
                Console.WriteLine("  " + it + "  " + rnrm2);

                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 + "");

        return(x);
    }