Exemplo n.º 1
0
    private static void test01()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST01 tests SPY_GE for a general storage matrix.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 June 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        const string header = "wathen_ge";

        Console.WriteLine("");
        Console.WriteLine("TEST01");
        Console.WriteLine("  SPY_GE generates a sparsity plot for a matrix stored");
        Console.WriteLine("  in general (GE) format.");

        const int nx   = 5;
        const int ny   = 5;
        int       n    = WathenMatrix.wathen_order(nx, ny);
        int       seed = 123456789;

        double[] a = WathenMatrix.wathen_ge(nx, ny, n, ref seed);

        Sparsity.spy_ge(n, n, a, header);
    }
Exemplo n.º 2
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) + "");
        }
    }
Exemplo n.º 3
0
    private static void wathen_xy_test()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    wathen_xy_test tests wathen_xy.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    18 February 2020
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int j;

        Console.WriteLine("");
        Console.WriteLine("wathen_xy_test");
        Console.WriteLine("  wathen_xy returns the (X,Y) coordinates of nodes in the");
        Console.WriteLine("  Wathen finite element system.");

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

        double[] xy = WathenMatrix.wathen_xy(nx, ny, n);

        Console.WriteLine("");
        Console.WriteLine("   k   i   j         x          y");
        Console.WriteLine("");

        int k = 0;

        for (j = 0; j <= 2 * ny; j++)
        {
            int i;
            switch (j % 2)
            {
            case 0:
            {
                for (i = 0; i <= 2 * ny; i++)
                {
                    Console.WriteLine("  " + k.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                      + "  " + i.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                      + "  " + j.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                      + "  " + xy[k].ToString(CultureInfo.InvariantCulture).PadLeft(8)
                                      + "  " + xy[k + n].ToString(CultureInfo.InvariantCulture).PadLeft(8) + "");
                    k += 1;
                }

                break;
            }

            default:
            {
                for (i = 0; i <= ny; i++)
                {
                    Console.WriteLine("  " + k.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                      + "  " + i.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                      + "  " + j.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                      + "  " + xy[k].ToString(CultureInfo.InvariantCulture).PadLeft(8)
                                      + "  " + xy[k + n].ToString(CultureInfo.InvariantCulture).PadLeft(8) + "");
                    k += 1;
                }

                break;
            }
            }
        }
    }
Exemplo n.º 4
0
    private static void test115()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST115 assembles, factors and solves using WATHEN_GB and CG_GB.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    08 June 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int i;
        int md = 0;
        int ml = 0;
        int mu = 0;

        Console.WriteLine("");
        Console.WriteLine("TEST115");
        Console.WriteLine("  Assemble, factor and solve a Wathen system");
        Console.WriteLine("  using WATHEN_GB and CG_GB.");
        Console.WriteLine("");

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

        Console.WriteLine("  Elements in X direction NX = " + nx + "");
        Console.WriteLine("  Elements in Y direction NY = " + ny + "");
        Console.WriteLine("  Number of elements = " + nx * ny + "");
        //
        //  Compute the number of unknowns.
        //
        int n = WathenMatrix.wathen_order(nx, ny);

        Console.WriteLine("  Number of nodes N = " + n + "");
        //
        //  Compute the bandwidth.
        //
        WathenMatrix.wathen_bandwidth(nx, ny, ref ml, ref md, ref mu);
        Console.WriteLine("  Lower bandwidth ML = " + ml + "");
        Console.WriteLine("  Upper bandwidth MU = " + mu + "");
        //
        //  Set up a random solution X1.
        //
        int seed = 123456789;

        double[] x1 = UniformRNG.r8vec_uniform_01_new(n, ref seed);
        //
        //  Compute the matrix.
        //
        seed = 123456789;
        double[] a = WathenMatrix.wathen_gb(nx, ny, n, ref seed);
        //
        //  Compute the corresponding right hand side B.
        //
        double[] b = MatbyVector.mv_gb(n, n, ml, mu, a, x1);
        //
        //  Solve the linear system.
        //
        double[] x2 = new double[n];
        for (i = 0; i < n; i++)
        {
            x2[i] = 1.0;
        }

        ConjugateGradient.cg_gb(n, ml, mu, a, b, ref x2);
        //
        //  Compute the maximum solution error.
        //
        double e = typeMethods.r8vec_diff_norm_li(n, x1, x2);

        Console.WriteLine("  Maximum solution error is " + e + "");
    }
Exemplo n.º 5
0
    private static void test11()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST11 assemble, factor and solve using WATHEN_ST + CG_ST.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    08 June 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int i;

        Console.WriteLine("");
        Console.WriteLine("TEST11");
        Console.WriteLine("  Assemble, factor and solve a Wathen system");
        Console.WriteLine("  defined by WATHEN_ST and CG_ST.");
        Console.WriteLine("");

        const int nx = 1;
        const int ny = 1;

        Console.WriteLine("  Elements in X direction NX = " + nx + "");
        Console.WriteLine("  Elements in Y direction NY = " + ny + "");
        Console.WriteLine("  Number of elements = " + nx * ny + "");
        //
        //  Compute the number of unknowns.
        //
        int n = WathenMatrix.wathen_order(nx, ny);

        Console.WriteLine("  Number of nodes N = " + n + "");
        //
        //  Set up a random solution X1.
        //
        int seed = 123456789;

        double[] x1 = UniformRNG.r8vec_uniform_01_new(n, ref seed);
        //
        //  Compute the matrix size.
        //
        int nz_num = WathenMatrix.wathen_st_size(nx, ny);

        Console.WriteLine("  Number of nonzeros NZ_NUM = " + nz_num + "");
        //
        //  Compute the matrix.
        //
        seed = 123456789;
        int[]    row = new int[nz_num];
        int[]    col = new int[nz_num];
        double[] a   = WathenMatrix.wathen_st(nx, ny, nz_num, ref seed, ref row, ref col);
        //
        //  Compute the corresponding right hand side B.
        //
        double[] b = MatbyVector.mv_st(n, n, nz_num, row, col, a, x1);
        //
        //  Solve the linear system.
        //
        double[] x2 = new double[n];
        for (i = 0; i < n; i++)
        {
            x2[i] = 1.0;
        }

        ConjugateGradient.cg_st(n, nz_num, row, col, a, b, ref x2);
        //
        //  Compute the maximum solution error.
        //
        double e = typeMethods.r8vec_diff_norm_li(n, x1, x2);

        Console.WriteLine("  Maximum solution error is " + e + "");
    }
Exemplo n.º 6
0
    private static void test01()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST01 assembles, factor and solve using WATHEN_GE.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    06 June 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int i;

        Console.WriteLine("");
        Console.WriteLine("TEST01");
        Console.WriteLine("  Assemble, factor and solve a Wathen system");
        Console.WriteLine("  defined by WATHEN_GE.");
        Console.WriteLine("");

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

        Console.WriteLine("  Elements in X direction NX = " + nx + "");
        Console.WriteLine("  Elements in Y direction NY = " + ny + "");
        Console.WriteLine("  Number of elements = " + nx * ny + "");
        //
        //  Compute the number of unknowns.
        //
        int n = WathenMatrix.wathen_order(nx, ny);

        Console.WriteLine("  Number of nodes N = " + n + "");
        //
        //  Set up a random solution X.
        //
        int seed = 123456789;

        double[] x1 = UniformRNG.r8vec_uniform_01_new(n, ref seed);
        //
        //  Compute the matrix.
        //
        seed = 123456789;
        double[] a = WathenMatrix.wathen_ge(nx, ny, n, ref seed);
        //
        //  Compute the corresponding right hand side B.
        //
        double[] b = MatbyVector.mv_ge(n, n, a, x1);
        //
        //  Solve the linear system.
        //
        int[] ipvt = new int[n];
        Matrix.dgefa(ref a, n, n, ref ipvt);

        double[] x2 = new double[n];
        for (i = 0; i < n; i++)
        {
            x2[i] = b[i];
        }

        int job = 0;

        Matrix.dgesl(a, n, n, ipvt, ref x2, job);
        //
        //  Compute the maximum solution error.
        //
        double e = typeMethods.r8vec_diff_norm_li(n, x1, x2);

        Console.WriteLine("  Maximum solution error is " + e + "");
    }
Exemplo n.º 7
0
    private static void test08()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST08 times WATHEN_GE/WATHEN_GB.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    08 June 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int md = 0;
        int ml = 0;
        int mu = 0;
        int test;

        Console.WriteLine("");
        Console.WriteLine("TEST08");
        Console.WriteLine("  For various problem sizes,");
        Console.WriteLine("  time the assembly and factorization of a Wathen system");
        Console.WriteLine("  WATHEN_GE/WATHEN_GB");
        Console.WriteLine("");
        Console.WriteLine("                   NX  Elements   Nodes   Storage    "
                          + "  Assembly      Factor      Error");

        int nx = 1;
        int ny = 1;

        for (test = 1; test <= 6; test++)
        {
            //
            //  Compute the number of unknowns.
            //
            int n          = WathenMatrix.wathen_order(nx, ny);
            int storage_ge = n * n;
            //
            //  Set up a random solution X1.
            //
            int      seed = 123456789;
            double[] x1   = UniformRNG.r8vec_uniform_01_new(n, ref seed);
            //
            //  Compute the matrix.
            //
            seed = 123456789;
            DateTime t0 = DateTime.Now;
            double[] a  = WathenMatrix.wathen_ge(nx, ny, n, ref seed);
            TimeSpan t1 = DateTime.Now - t0;
            //
            //  Compute the corresponding right hand side B.
            //
            double[] b = MatbyVector.mv_ge(n, n, a, x1);
            //
            //  Solve the system.
            //
            int[]    ipvt = new int[n];
            double[] x2   = new double[n];
            int      i;
            for (i = 0; i < n; i++)
            {
                x2[i] = b[i];
            }

            int job = 0;

            t0 = DateTime.Now;
            Matrix.dgefa(ref a, n, n, ref ipvt);
            Matrix.dgesl(a, n, n, ipvt, ref x2, job);
            TimeSpan t2 = DateTime.Now - t0;
            //
            //  Compute the maximum solution error.
            //
            double e = typeMethods.r8vec_diff_norm_li(n, x1, x2);
            //
            //  Report.
            //
            Console.WriteLine("");
            Console.WriteLine("  WATHEN_GE      "
                              + nx.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "      "
                              + (nx * ny).ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                              + n.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  "
                              + storage_ge.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                              + t1.TotalSeconds.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "  "
                              + t2.TotalSeconds.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "  "
                              + e.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "");

            //
            //  Compute the bandwidth.
            //
            WathenMatrix.wathen_bandwidth(nx, ny, ref ml, ref md, ref mu);
            int
                storage_gb = (2 * ml + mu + 1) * n;
            //
            //  Set up a random solution X1.
            //
            seed = 123456789;
            x1   = UniformRNG.r8vec_uniform_01_new(n, ref seed);
            //
            //  Compute the matrix.
            //
            seed = 123456789;
            t0   = DateTime.Now;
            a    = WathenMatrix.wathen_gb(nx, ny, n, ref seed);
            t1   = DateTime.Now - t0;
            //
            //  Compute the corresponding right hand side B.
            //
            b = MatbyVector.mv_gb(n, n, ml, mu, a, x1);
            //
            //  Solve the system.
            //
            int lda = 2 * ml + mu + 1;
            ipvt = new int[n];
            x2   = new double[n];
            for (i = 0; i < n; i++)
            {
                x2[i] = b[i];
            }

            job = 0;

            t0 = DateTime.Now;
            Matrix.dgbfa(ref a, lda, n, ml, mu, ref ipvt);
            Matrix.dgbsl(a, lda, n, ml, mu, ipvt, ref x2, job);
            t2 = DateTime.Now - t0;
            //
            //  Compute the maximum solution error.
            //
            e = typeMethods.r8vec_diff_norm_li(n, x1, x2);
            //
            //  Report.
            //
            Console.WriteLine("  WATHEN_GB      "
                              + nx.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "      "
                              + (nx * ny).ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                              + n.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  "
                              + storage_gb.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                              + t1.TotalSeconds.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "  "
                              + t2.TotalSeconds.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "  "
                              + e.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "");
            //
            //  Ready for next iteration.
            //
            nx *= 2;
            ny *= 2;
        }
    }
Exemplo n.º 8
0
    private static void test05()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST05 measures the storage needed for the Wathen system.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    08 June 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int bd1 = 0;
        int bd2 = 0;
        int bl1 = 0;
        int bl2 = 0;
        int bu1 = 0;
        int bu2 = 0;
        int bw2 = 0;

        Console.WriteLine("");
        Console.WriteLine("TEST05");
        Console.WriteLine("  For various problem sizes and storage schemes,");
        Console.WriteLine("  measure the storage used for the Wathen system.");
        Console.WriteLine("");
        Console.WriteLine("                                   Predicted  Observed");
        Console.WriteLine("                              GE        Band      Band      "
                          + "Band    Sparse");
        Console.WriteLine("    NX  Elements   Nodes   storage     width     width   "
                          + "  storage   storage");
        Console.WriteLine("");

        int nx = 1;
        int ny = 1;

        for (int test = 1; test <= 6; test++)
        {
            //
            //  Compute the number of unknowns.
            //
            int n = WathenMatrix.wathen_order(nx, ny);
            //
            //  Predict the bandwidth.
            //
            WathenMatrix.wathen_bandwidth(nx, ny, ref bl1, ref bd1, ref bu1);
            int bw1 = bl1 + bd1 + bu1;
            //
            //  Compute the matrix.
            //
            int      seed = 123456789;
            double[] a    = WathenMatrix.wathen_ge(nx, ny, n, ref seed);

            int storage_ge = n * n;

            Matrix.bandwidth(n, n, a, ref bw2, ref bl2, ref bd2, ref bu2);
            int storage_gb = (2 * bl2 + 1 + bu2) * n;

            int storage_sparse = Matrix.nonzeros(n, n, a);
            //
            //  Report.
            //
            Console.WriteLine(nx.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "      "
                              + (nx * ny).ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                              + n.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  "
                              + storage_ge.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                              + bw1.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                              + bw2.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                              + storage_gb.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "  "
                              + storage_sparse.ToString(CultureInfo.InvariantCulture).PadLeft(8) + "");
            //
            //  Ready for next iteration.
            //
            nx *= 2;
            ny *= 2;
        }
    }
Exemplo n.º 9
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:");
    }