Exemple #1
0
    private static void test10()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST10 tests TRIANGULATION_NEIGHBOR_TRIANGLES.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    28 September 2009
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int TRIANGLE_ORDER = 3;
        int TRIANGLE_NUM   = 16;

        int[] triangle_node =
        {
            3,   4,  1,
            3,   1,  2,
            3,   2,  8,
            2,   1,  5,
            8,   2, 13,
            8,  13,  9,
            3,   8,  9,
            13,  2,  5,
            9,  13,  7,
            7,  13,  5,
            6,   7,  5,
            9,   7,  6,
            10,  9,  6,
            6,   5, 12,
            11,  6, 12,
            10,  6, 11
        };

        Console.WriteLine("");
        Console.WriteLine("TEST10");
        Console.WriteLine("  For a triangulation of a set of nodes,");
        Console.WriteLine("  TRIANGULATION_NEIGHBOR_TRIANGLES determines the");
        Console.WriteLine("    adjacency relationships between triangles.");

        typeMethods.i4mat_transpose_print(TRIANGLE_ORDER, TRIANGLE_NUM, triangle_node,
                                          "  Triangles:");

        int[] triangle_neighbor = NeighborElements.triangulation_neighbor_triangles(TRIANGLE_ORDER,
                                                                                    TRIANGLE_NUM, triangle_node);

        typeMethods.i4mat_transpose_print(3, TRIANGLE_NUM, triangle_neighbor,
                                          "  Triangle neighbors:");
    }
Exemple #2
0
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for TRIANGULATION_DELAUNAY_DISCREPANCY.
    //
    //  Discussion:
    //
    //    TRIANGULATION_DELAUNAY_DISCREPANCY measures the amount (possibly zero)
    //    by which a triangulation fails the local Delaunay test.
    //
    //    The local Delaunay considers pairs of neighboring triangles.
    //    The two triangles form a quadrilateral, and their common edge is one
    //    diagonal of that quadrilateral.  The program considers the effect of
    //    replacing that diagonal with the other one.  If the minimum angle
    //    of the original configuration is smaller than in the new configuration,
    //    then the pair of triangles has failed the local Delaunay test.
    //    The amount by which the minimum angle would have increased is the
    //    local discrepancy.
    //
    //    This program searches all pairs of triangles, and records the maximum
    //    discrepancy found.  If this discrepancy is essentially zero, then the
    //    triangulation is a Delaunay triangulation.  Otherwise, it is not a
    //    Delaunay triangulation.
    //
    //    The user supplies a node file and a triangle file, containing
    //    the coordinates of the nodes, and the indices of the nodes that
    //    make up each triangle.  Either 3-node or 6-node triangles may
    //    be used.
    //
    //    The program reads the node and triangle data, computes the triangle
    //    neighbor information, and writes it to a file.
    //
    //  Usage:
    //
    //    triangulation_delaunay_discrepancy prefix
    //
    //    where 'prefix' is the common filename prefix:
    //
    //    * prefix_nodes.txt contains the node coordinates,
    //    * prefix_elements.txt contains the element definitions.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    06 May 2020
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        double angle_max          = 0;
        int    angle_max_triangle = 0;
        double angle_min          = 0;
        int    angle_min_triangle = 0;
        string prefix;

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_DELAUNAY_DISCREPANCY:");
        Console.WriteLine("");
        Console.WriteLine("  Read a node dataset of NODE_NUM points in 2 dimensions.");
        Console.WriteLine("  Read an associated triangulation dataset of ");
        Console.WriteLine("  TRIANGLE_NUM triangles using 3 or 6 nodes.");
        Console.WriteLine("");
        Console.WriteLine("  Determine the Delaunay discrepancy, that is, the amount");
        Console.WriteLine("  by which the minimum angle in the triangulation could be");
        Console.WriteLine("  changed by a single adjustment of a pair of triangles.");
        Console.WriteLine("");
        Console.WriteLine("  If this discrepancy is negative, ");
        Console.WriteLine("  then the triangulation is not a Delaunay triangulation.");
        Console.WriteLine("");
        Console.WriteLine("  If this discrepancy is 0 or essentially so, ");
        Console.WriteLine("  then the triangulation is a Delaunay triangulation.");
        //
        //  Get the filename prefix.
        //
        try
        {
            prefix = args[0];
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_DELAUNAY_DISCREPANCY:");
            Console.WriteLine("  Please enter the filename prefix.");

            prefix = Console.ReadLine();
        }

        //
        //  Create the filenames.
        //
        string node_filename    = prefix + "_nodes.txt";
        string element_filename = prefix + "_elements.txt";
        //
        //  Read the node data.
        //
        TableHeader h        = typeMethods.r8mat_header_read(node_filename);
        int         dim_num  = h.m;
        int         node_num = h.n;

        Console.WriteLine("");
        Console.WriteLine("  Read the header of \"" + node_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Spatial dimension DIM_NUM = " + dim_num + "");
        Console.WriteLine("  Number of nodes NODE_NUM  = " + node_num + "");

        double[] node_xy = typeMethods.r8mat_data_read(node_filename, dim_num, node_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + node_filename + "\".");

        typeMethods.r8mat_transpose_print_some(dim_num, node_num, node_xy, 1, 1, dim_num, 5,
                                               "  First 5 nodes:");
        //
        //  Read the triangulation data.
        //
        h = typeMethods.i4mat_header_read(element_filename);
        int triangle_order = h.m;
        int triangle_num   = h.n;

        Console.WriteLine("");
        Console.WriteLine(" Read the header of \"" + element_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Triangle order TRIANGLE_ORDER = " + triangle_order + "");
        Console.WriteLine("  Number of triangles TRIANGLE_NUM  = " + triangle_num + "");

        int[] triangle_node = typeMethods.i4mat_data_read(element_filename, triangle_order, triangle_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + element_filename + "\".");

        typeMethods.i4mat_transpose_print_some(triangle_order, triangle_num, triangle_node,
                                               1, 1, triangle_order, 10, "  First 10 triangles:");
        //
        //  Detect and correct 1-based node indexing.
        //
        Mesh.mesh_base_zero(node_num, triangle_order, triangle_num, ref triangle_node);
        //
        //  Create the triangle neighbors.
        //
        int[] triangle_neighbor = NeighborElements.triangulation_neighbor_triangles(triangle_order,
                                                                                    triangle_num, triangle_node);

        //
        //  Convert to 0-based index.
        //
        for (int j = 0; j < triangle_num; j++)
        {
            for (int i = 0; i < 3; i++)
            {
                triangle_neighbor[i + 3 * j] -= 1;
            }
        }

        typeMethods.i4mat_transpose_print_some(3, triangle_num, triangle_neighbor,
                                               1, 1, 3, 10, "  First 10 triangle neighbors:");
        //
        //  Now we are ready to check.
        //
        double discrepancy = Delauney.triangulation_delaunay_discrepancy_compute(node_num, node_xy,
                                                                                 triangle_order, triangle_num, triangle_node, triangle_neighbor, ref angle_min,
                                                                                 ref angle_min_triangle, ref angle_max, ref angle_max_triangle);

        Console.WriteLine("");
        Console.WriteLine("  Discrepancy (degrees) =   " + discrepancy + "");
        Console.WriteLine("  Minimum angle (degrees) = " + angle_min + "");
        Console.WriteLine("  occurred in triangle      " + angle_min_triangle + "");
        Console.WriteLine("  Maximum angle (degrees) = " + angle_max + "");
        Console.WriteLine("  occurred in triangle      " + angle_max_triangle + "");

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_DELAUNAY_DISCREPANCY:");
        Console.WriteLine("  Normal end of execution.");
        Console.WriteLine("");
    }
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for TRIANGULATION_TRIANGLE_NEIGHBORS.
    //
    //  Discussion:
    //
    //    TRIANGULATION_TRIANGLE_NEIGHBORS determines the neighbor triangles
    //    of each triangle in a triangulation.
    //
    //    The user supplies a node file and a triangle file, containing
    //    the coordinates of the nodes, and the indices of the nodes that
    //    make up each triangle.  Either 3-node or 6-node triangles may
    //    be used.
    //
    //    The program reads the node and triangle data, computes the triangle
    //    neighbor information, and writes it to a file.
    //
    //  Usage:
    //
    //    triangulation_triangle_neighbors prefix
    //
    //    where 'prefix' is the common filename prefix:
    //
    //    * prefix_nodes.txt contains the node coordinates,
    //    * prefix_elements.txt contains the element definitions.
    //    * prefix_element_neighbors.txt will contain the triangle neighbors.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    04 October 2009
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        string prefix;

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_TRIANGLE_NEIGHBORS.");
        Console.WriteLine("  Read a node dataset of NODE_NUM points in 2 dimensions.");
        Console.WriteLine("  Read an associated triangulation dataset of ");
        Console.WriteLine("  TRIANGLE_NUM triangles using 3 or 6 nodes.");
        Console.WriteLine("");
        Console.WriteLine("  For each triangle, determine the indices of the");
        Console.WriteLine("  triangles opposite vertices 1, 2 and 3.");
        Console.WriteLine("");
        Console.WriteLine("  Write this triangle neighbor data to files.");
        Console.WriteLine("");
        //
        //  Get the filename prefix.
        //
        try
        {
            prefix = args[0];
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_TRIANGLE_NEIGHBORS:");
            Console.WriteLine("  Please enter the filename prefix.");

            prefix = Console.ReadLine();
        }

        //
        //  Create the filenames.
        //
        string node_filename     = prefix + "_nodes.txt";
        string element_filename  = prefix + "_elements.txt";
        string neighbor_filename = prefix + "_neighbors.txt";
        //
        //  Read the node data.
        //
        TableHeader h        = typeMethods.r8mat_header_read(node_filename);
        int         dim_num  = h.m;
        int         node_num = h.n;

        Console.WriteLine("");
        Console.WriteLine("  Read the header of \"" + node_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Spatial dimension DIM_NUM = " + dim_num + "");
        Console.WriteLine("  Number of nodes NODE_NUM  = " + node_num + "");

        double[] node_xy = typeMethods.r8mat_data_read(node_filename, dim_num, node_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + node_filename + "\".");

        typeMethods.r8mat_transpose_print_some(dim_num, node_num, node_xy, 1, 1, dim_num, 5,
                                               "  Portion of coordinate data from file:");
        //
        //  Read the element data.
        //
        h = typeMethods.i4mat_header_read(element_filename);
        int triangle_order = h.m;
        int triangle_num   = h.n;

        Console.WriteLine("");
        Console.WriteLine(" Read the header of \"" + element_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Triangle order TRIANGLE_ORDER = " + triangle_order + "");
        Console.WriteLine("  Number of triangles TRIANGLE_NUM  = " + triangle_num + "");

        int[] triangle_node = typeMethods.i4mat_data_read(element_filename,
                                                          triangle_order, triangle_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + element_filename + "\".");

        typeMethods.i4mat_transpose_print_some(triangle_order, triangle_num, triangle_node, 1, 1,
                                               triangle_order, 5, "  Portion of data read from file:");
        //
        //  Detect and correct 1-based node indexing.
        //
        Mesh.mesh_base_zero(node_num, triangle_order, triangle_num, ref triangle_node);
        //
        //  Create the triangle neighbors.
        //
        int[] triangle_neighbor = NeighborElements.triangulation_neighbor_triangles(triangle_order,
                                                                                    triangle_num, triangle_node);
        //
        //  Write the output file.
        //
        typeMethods.i4mat_write(neighbor_filename, 3, triangle_num, triangle_neighbor);

        Console.WriteLine("");
        Console.WriteLine("  Created the triangle neighbor file \""
                          + neighbor_filename + "\"");


        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_TRIANGLE_NEIGHBORS.:");
        Console.WriteLine("  Normal end of execution.");

        Console.WriteLine("");
    }
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for TRIANGULATION_L2Q.
    //
    //  Discussion:
    //
    //    TRIANGULATION_L2Q makes a quadratic triangulation from a linear one.
    //
    //    Thanks to Zhu Wang for pointing out a problem caused by a change
    //    in the ordering of elements in the triangle neighbor array, 25 August 2010.
    //
    //  Usage:
    //
    //    triangulation_l2q prefix
    //
    //    where 'prefix' is the common filename prefix:
    //
    //    * prefix_nodes.txt contains the linear node coordinates,
    //    * prefix_elements.txt contains the linear element definitions.
    //    * prefix_l2q_nodes.txt will contain the quadratic node coordinates,
    //    * prefix_l2q_elements.txt will contain the quadratic element definitions.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    25 August 2010
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int    element;
        int    i;
        string prefix;

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_L2Q");
        Console.WriteLine("  Read a \"linear\" triangulation and");
        Console.WriteLine("  write out a \"quadratic\" triangulation.");
        Console.WriteLine("");
        Console.WriteLine("  Read a dataset of NODE_NUM1 points in 2 dimensions.");
        Console.WriteLine("  Read an associated triangulation dataset of ELEMENT_NUM ");
        Console.WriteLine("  elements which uses 3 nodes per triangular element.");
        Console.WriteLine("");
        Console.WriteLine("  Create new nodes which are triangle midpoints,");
        Console.WriteLine("  generate new node and triangulation data for");
        Console.WriteLine("  quadratic 6-node elements, and write them out.");
        Console.WriteLine("");
        //
        //  Get the filename prefix.
        //
        try
        {
            prefix = args[0];
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_L2Q:");
            Console.WriteLine("  Please enter the filename prefix.");

            prefix = Console.ReadLine();
        }

        //
        //  Create the filenames.
        //
        string node_filename        = prefix + "_nodes.txt";
        string element_filename     = prefix + "_elements.txt";
        string node_l2q_filename    = prefix + "_l2q_nodes.txt";
        string element_l2q_filename = prefix + "_l2q_elements.txt";
        //
        //  Read the data.
        //
        TableHeader h         = typeMethods.r8mat_header_read(node_filename);
        int         m         = h.m;
        int         node_num1 = h.n;

        Console.WriteLine("");
        Console.WriteLine("  Read the header of \"" + node_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Spatial dimension M = " + m + "");
        Console.WriteLine("  Number of nodes NODE_NUM1  = " + node_num1 + "");

        double[] node_xy1 = typeMethods.r8mat_data_read(node_filename, m, node_num1);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + node_filename + "\".");

        typeMethods.r8mat_transpose_print_some(m, node_num1, node_xy1, 1, 1, m, 10,
                                               "  Portion of node coordinate data:");
        //
        //  Read the element data.
        //
        h = typeMethods.i4mat_header_read(element_filename);
        int element_order1 = h.m;
        int element_num    = h.n;

        if (element_order1 != 3)
        {
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_L2Q - Fatal error!");
            Console.WriteLine("  Data is not for a 3-node triangulation.");
            return;
        }

        Console.WriteLine("");
        Console.WriteLine("  Read the header of \"" + element_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Element order = " + element_order1 + "");
        Console.WriteLine("  Number of elements  = " + element_num + "");

        int[] element_node1 = typeMethods.i4mat_data_read(element_filename, element_order1,
                                                          element_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + element_filename + "\".");

        typeMethods.i4mat_transpose_print_some(element_order1, element_num, element_node1,
                                               1, 1, element_order1, 10, "  First 10 elements:");
        //
        //  Detect and correct 1-based node indexing.
        //
        Mesh.mesh_base_zero(node_num1, element_order1, element_num, ref element_node1);
        //
        //  Determine the number of midside nodes that will be added.
        //
        int boundary_num = Boundary.triangulation_order3_boundary_edge_count(element_num,
                                                                             element_node1);

        int interior_num = (3 * element_num - boundary_num) / 2;
        int edge_num     = interior_num + boundary_num;

        Console.WriteLine("");
        Console.WriteLine("  Number of midside nodes to add = " + edge_num + "");
        //
        //  Allocate space.
        //
        int node_num2      = node_num1 + edge_num;
        int element_order2 = 6;

        double[] node_xy2      = new double[m * node_num2];
        int[]    element_node2 = new int[element_order2 * element_num];
        //
        //  Build the element neighbor array.
        //
        int[] element_neighbor = NeighborElements.triangulation_neighbor_triangles(element_order1,
                                                                                   element_num, element_node1);

        typeMethods.i4mat_transpose_print(3, element_num, element_neighbor,
                                          "  Element_neighbor:");
        //
        //  Create the midside nodes.
        //
        for (element = 0; element < element_num; element++)
        {
            for (i = 0; i < 3; i++)
            {
                element_node2[i + element * 6] = element_node1[i + element * 3];
            }

            for (i = 3; i < 6; i++)
            {
                element_node2[i + element * 6] = -1;
            }
        }

        for (i = 0; i < m; i++)
        {
            int node;
            for (node = 0; node < node_num1; node++)
            {
                node_xy2[i + node * 2] = node_xy1[i + node * 2];
            }

            for (node = node_num1; node < node_num2; node++)
            {
                node_xy2[i + node * 2] = -1.0;
            }
        }

        node_num2 = node_num1;

        Console.WriteLine("");
        Console.WriteLine("  Generate midside nodes");
        Console.WriteLine("");

        for (element = 1; element <= element_num; element++)
        {
            for (i = 0; i < 3; i++)
            {
                //
                //  CORRECTION #1 because element neighbor definition was changed.
                //
                int iii      = typeMethods.i4_wrap(i + 2, 0, 2);
                int element2 = element_neighbor[iii + (element - 1) * 3];

                switch (element2)
                {
                case > 0 when element2 < element:
                    continue;
                }

                int ip1 = typeMethods.i4_wrap(i + 1, 0, 2);
                //
                //  Temporary RETRO FIX!
                //
                int k1 = element_node2[i + (element - 1) * 6] + 1;
                int k2 = element_node2[ip1 + (element - 1) * 6] + 1;

                string cout = "  " + node_num2.ToString(CultureInfo.InvariantCulture).PadLeft(8);
                int    ii;
                for (ii = 0; ii < 2; ii++)
                {
                    node_xy2[(node_xy2.Length + ii + node_num2 * m) % node_xy2.Length] = 0.5
                                                                                         * (node_xy1[(ii + (k1 - 1) * m + node_xy1.Length) % node_xy1.Length] + node_xy1[(ii + (k2 - 1) * m + node_xy1.Length) % node_xy1.Length]);
                    cout += "  " + node_xy2[(ii + node_num2 * m + node_xy2.Length) % node_xy2.Length].ToString(CultureInfo.InvariantCulture).PadLeft(12);
                }

                Console.WriteLine(cout);

                element_node2[3 + i + (element - 1) * 6] = node_num2;

                switch (element2)
                {
                case > 0:
                {
                    for (ii = 0; ii < 3; ii++)
                    {
                        //
                        //  CORRECTION #2 because element neighbor definition changed.
                        //
                        iii = typeMethods.i4_wrap(ii + 2, 0, 2);
                        if (element_neighbor[iii + (element2 - 1) * 3] == element)
                        {
                            element_node2[ii + 3 + (element2 - 1) * 6] = node_num2;
                        }
                    }

                    break;
                }
                }

                node_num2 += 1;
            }
        }

        typeMethods.i4mat_transpose_print(element_order2, element_num, element_node2,
                                          "  ELEMENT_NODE2:");
        //
        //  Write out the node and element data for the quadratic mesh.
        //
        typeMethods.r8mat_transpose_print(m, node_num2, node_xy2, "  NODE_XY2:");

        typeMethods.r8mat_write(node_l2q_filename, m, node_num2, node_xy2);

        typeMethods.i4mat_write(element_l2q_filename, element_order2, element_num,
                                element_node2);

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_L2Q:");
        Console.WriteLine("  Normal end of execution.");
        Console.WriteLine("");
    }
    private static void Main(string[] args)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for TRIANGULATION_RCM.
    //
    //  Discussion:
    //
    //    TRIANGULATION_RCM applies the RCM reordering to a triangulation.
    //
    //    The user supplies a node file and a triangle file, containing
    //    the coordinates of the nodes, and the indices of the nodes that
    //    make up each triangle.  Either 3-node or 6-node triangles may
    //    be used.
    //
    //    The program reads the data, computes the adjacency information,
    //    carries out the RCM algorithm to get the permutation, applies
    //    the permutation to the nodes and triangles, and writes out
    //    new node and triangle files that correspond to the RCM permutation.
    //
    //    Note that node data is normally two dimensional, that is,
    //    each node has an X and Y coordinate.  In some applications, it
    //    may be desirable to specify more information.  This program
    //    will accept node data that includes DIM_NUM entries on each line,
    //    as long as DIM_NUM is the same for each entry.
    //
    //  Usage:
    //
    //    triangulation_rcm prefix
    //
    //    where 'prefix' is the common filename prefix:
    //
    //    * prefix_nodes.txt contains the node coordinates,
    //    * prefix_elements.txt contains the element definitions.
    //    * prefix_rcm_nodes.txt will contain the RCM node coordinates,
    //    * prefix_rcm_elements.txt will contain the RCM element definitions.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    28 September 2009
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int[] adj     = null;
        int   adj_num = 0;

        int[]  adj_row = null;
        int    j;
        string prefix;

        Console.WriteLine("");

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_RCM");
        Console.WriteLine("  C++ version:");
        Console.WriteLine("  Read a node dataset of NODE_NUM points in 2 dimensions.");
        Console.WriteLine("  Read an associated triangulation dataset of TRIANGLE_NUM");
        Console.WriteLine("  triangles using 3 or 6 nodes.");
        Console.WriteLine("");
        Console.WriteLine("  Apply the RCM reordering (Reverse Cuthill-McKee).");
        Console.WriteLine("");
        Console.WriteLine("  Reorder the data and write it out to files.");
        Console.WriteLine("");
        //
        //  Get the filename prefix.
        //
        try
        {
            prefix = args[0];
        }
        catch
        {
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_RCM");
            Console.WriteLine("  Please enter the filename prefix.");

            prefix = Console.ReadLine();
        }

        //
        //  Create the filenames.
        //
        string node_filename        = prefix + "_nodes.txt";
        string element_filename     = prefix + "_elements.txt";
        string node_rcm_filename    = prefix + "_rcm_nodes.txt";
        string element_rcm_filename = prefix + "_rcm_elements.txt";
        //
        //  Read the node data.
        //
        TableHeader h        = typeMethods.r8mat_header_read(node_filename);
        int         dim_num  = h.m;
        int         node_num = h.n;

        Console.WriteLine("");
        Console.WriteLine("  Read the header of \"" + node_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Spatial dimension DIM_NUM = " + dim_num + "");
        Console.WriteLine("  Number of nodes NODE_NUM =  " + node_num + "");

        double[] node_xy = typeMethods.r8mat_data_read(node_filename, dim_num, node_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + node_filename + "\".");

        typeMethods.r8mat_transpose_print_some(dim_num, node_num, node_xy, 1, 1,
                                               dim_num, 5, "  Coordinates of first 5 nodes:");
        //
        //  Read the element data.
        //
        h = typeMethods.i4mat_header_read(element_filename);
        int triangle_order = h.m;
        int triangle_num   = h.n;

        Console.WriteLine("");
        Console.WriteLine("  Read the header of \"" + element_filename + "\".");
        Console.WriteLine("");
        Console.WriteLine("  Triangle order TRIANGLE_ORDER = " + triangle_order + "");
        Console.WriteLine("  Number of triangles TRIANGLE_NUM = " + triangle_num + "");

        if (triangle_order != 3 && triangle_order != 6)
        {
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_RCM - Fatal error!");
            Console.WriteLine("  Data is not for a 3-node or 6-node triangulation.");
            return;
        }

        int[] triangle_node = typeMethods.i4mat_data_read(element_filename,
                                                          triangle_order, triangle_num);

        Console.WriteLine("");
        Console.WriteLine("  Read the data in \"" + element_filename + "\".");

        typeMethods.i4mat_transpose_print_some(triangle_order, triangle_num, triangle_node, 1, 1,
                                               triangle_order, 10, "  First 5 triangles::");
        //
        //  Detect and correct 1-based node indexing.
        //
        Mesh.mesh_base_zero(node_num, triangle_order, triangle_num, ref triangle_node);
        //
        //  Create the element neighbor array.
        //
        int[] triangle_neighbor = NeighborElements.triangulation_neighbor_triangles(triangle_order,
                                                                                    triangle_num, triangle_node);
        switch (triangle_order)
        {
        //
        //  Set up the information needed for the RCM computation.
        //
        case 3:
            //
            //  Count the number of adjacencies, and set up the ADJ_ROW
            //  adjacency pointer array.
            //
            adj_row = new int [node_num + 1];

            adj_num = Adjacency.triangulation_order3_adj_count(node_num, triangle_num,
                                                               triangle_node, triangle_neighbor, adj_row);
            //
            //  Set up the ADJ adjacency array.
            //
            adj = Adjacency.triangulation_order3_adj_set(node_num, triangle_num, triangle_node,
                                                         triangle_neighbor, adj_num, adj_row);
            break;

        case 6:
            //
            //  Count the number of adjacencies, and set up the ADJ_ROW
            //  adjacency pointer array.
            //
            adj_row = new int [node_num + 1];

            adj_num = Adjacency.triangulation_order6_adj_count(node_num, triangle_num,
                                                               triangle_node, ref triangle_neighbor, ref adj_row);
            //
            //  Set up the ADJ adjacency array.
            //
            adj = Adjacency.triangulation_order6_adj_set(node_num, triangle_num, triangle_node,
                                                         triangle_neighbor, adj_num, adj_row);
            break;
        }

        int bandwidth = AdjacencyMatrix.adj_bandwidth(node_num, adj_num, adj_row, adj);

        Console.WriteLine("");
        Console.WriteLine("  ADJ bandwidth = " + bandwidth + "");
        //
        //  Compute the RCM permutation.
        //
        int[] perm = new int[node_num];

        perm = Burkardt.Graph.GenRCM.genrcm(node_num, adj_num, adj_row, adj);

        int[] perm_inv = new int[node_num];

        typeMethods.perm_inverse3(node_num, perm, ref perm_inv);

        bandwidth = AdjacencyMatrix.adj_perm_bandwidth(node_num, adj_num, adj_row, adj,
                                                       perm, perm_inv);

        Console.WriteLine("");
        Console.WriteLine("  Permuted ADJ bandwidth = " + bandwidth + "");
        //
        //  Permute the nodes according to the permutation vector.
        //
        typeMethods.r8col_permute(dim_num, node_num, perm, ref node_xy);
        //
        //  Permute the node indices in the triangle array.
        //
        for (j = 0; j < triangle_num; j++)
        {
            int i;
            for (i = 0; i < triangle_order; i++)
            {
                int node = triangle_node[i + j * triangle_order];
                triangle_node[i + j * triangle_order] = perm_inv[node - 1];
            }
        }

        //
        //  Write out the new data.
        //
        typeMethods.r8mat_write(node_rcm_filename, dim_num, node_num, node_xy);

        Console.WriteLine("");
        Console.WriteLine("  Created the node file \"" + node_rcm_filename + "\".");

        typeMethods.i4mat_write(element_rcm_filename, triangle_order,
                                triangle_num, triangle_node);

        Console.WriteLine("");
        Console.WriteLine("  Created the triangulation file \"" +
                          element_rcm_filename + "\".");

        Console.WriteLine("");
        Console.WriteLine("TRIANGULATION_RCM:");
        Console.WriteLine("  Normal end of execution.");

        Console.WriteLine("");
    }