private static void Main(string[] args) //****************************************************************************80 // // Purpose: // // MAIN is the main program for TET_MESH_RCM. // // Discussion: // // TET_MESH_RCM applies the RCM reordering to a tet mesh. // // The user supplies a node file and a tetrahedron file, containing // the coordinates of the nodes, and the indices of the nodes that // make up each tetrahedron. Either 4-node or 10-node tetrahedrons 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 tetrahedrons, and writes out // new node and tetrahedron files that correspond to the RCM permutation. // // Note that node data is normally three dimensional, that is, // each node has an X, Y and Z 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. // // Thanks to Xingxing Zhang for pointing out some problems with a // previous version of this program, 10 May 2011. // // Usage: // // tet_mesh_rcm prefix // // where prefix is the common file prefix: // // * prefix_nodes.txt, the node coordinates (input); // * prefix_elements.txt, the element definitions (input). // * prefix_rcm_nodes.txt, the new node coordinates (output); // * prefix_rcm_elements.txt, the new element definitions (output). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 March 2013 // // Author: // // John Burkardt // { int[] adj = new int[1]; int adj_num = 0; int[] adj_row = new int[1]; const bool debug = false; int i; int j; string prefix; Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine("TET_MESH_RCM"); Console.WriteLine(" Read a node dataset of NODE_NUM points in 3 dimensions."); Console.WriteLine(" Read an associated tet mesh dataset of TETRA_NUM"); Console.WriteLine(" tetrahedrons using 4 or 10 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("TET_MESH_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 points NODE_NUM = " + node_num + ""); double[] node_xyz = 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_xyz, 1, 1, dim_num, 5, " Coordinates of first 5 nodes:"); // // Read the tet mesh data. // h = typeMethods.i4mat_header_read(element_filename); int element_order = h.m; int element_num = h.n; if (element_order != 4 && element_order != 10) { Console.WriteLine(""); Console.WriteLine("TET_MESH_RCM - Fatal error!"); Console.WriteLine(" The tet mesh must have order 4 or order 10."); return; } Console.WriteLine(""); Console.WriteLine(" Read the header of \"" + element_filename + "\"."); Console.WriteLine(""); Console.WriteLine(" Tetrahedron order = " + element_order + ""); Console.WriteLine(" Number of tetras = " + element_num + ""); int[] element_node = typeMethods.i4mat_data_read(element_filename, element_order, element_num); Console.WriteLine(""); Console.WriteLine(" Read the data in \"" + element_filename + "\"."); typeMethods.i4mat_transpose_print_some(element_order, element_num, element_node, 1, 1, element_order, 5, " First 5 tetrahedrons:"); // // If the element information is 1-based, make it 0-based. // int base_user = TetMesh.tet_mesh_base_zero(node_num, element_order, element_num, ref element_node); if (base_user != 0 && base_user != 1) { Console.WriteLine(""); Console.WriteLine("TET_MESH_RCM - Fatal error!"); Console.WriteLine(" The input data does not seem to be 0-based or 1-based."); } switch (element_order) { // // Following code depends on the element order. // case 4: { // // Count the number of adjacencies. // Set up the ADJ_ROW adjacency pointer array. // adj_row = new int[node_num + 1]; TetMesh.tet_mesh_order4_adj_count(node_num, element_num, element_node, ref adj_num, ref adj_row); if (debug || node_num < 10) { Console.WriteLine(""); Console.WriteLine(" ADJ_NUM = " + adj_num + ""); typeMethods.i4vec_print(node_num + 1, adj_row, " ADJ_ROW:"); } // // Set up the ADJ adjacency array. // adj = TetMesh.tet_mesh_order4_adj_set(node_num, element_num, element_node, adj_num, adj_row); switch (node_num) { case < 10: AdjacencyMatrix.adj_print(node_num, adj_num, adj_row, adj, " ADJ"); break; } break; } case 10: { // // Count the number of adjacencies. // Set up the ADJ_ROW adjacency pointer array. // adj_row = new int[node_num + 1]; TetMesh.tet_mesh_order10_adj_count(node_num, element_num, element_node, ref adj_num, ref adj_row); if (debug || node_num < 10) { Console.WriteLine(""); Console.WriteLine(" ADJ_NUM = " + adj_num + ""); typeMethods.i4vec_print(node_num + 1, adj_row, " ADJ_ROW:"); } // // Set up the ADJ adjacency array. // adj = TetMesh.tet_mesh_order10_adj_set(node_num, element_num, element_node, ref adj_num, ref adj_row); switch (node_num) { case < 10: AdjacencyMatrix.adj_print(node_num, adj_num, adj_row, adj, " ADJ"); break; } break; } } // // Compute the bandwidth. // int bandwidth = AdjacencyMatrix.adj_bandwidth(node_num, adj_num, adj_row, adj); Console.WriteLine(""); Console.WriteLine(" ADJ bandwidth = " + bandwidth + ""); // // GENRCM computes the RCM permutation. // int[] perm = GenRCM.genrcm(node_num, adj_num, adj_row, adj); // // Compute the inverse permutation. // int[] perm_inv = typeMethods.perm_inverse3(node_num, perm); switch (node_num) { case < 10: { Console.WriteLine(""); Console.WriteLine(" I PERM[I] INVERSE[I]"); Console.WriteLine(""); for (i = 0; i < node_num; i++) { Console.WriteLine(" " + i.ToString().PadLeft(8) + " " + perm[i].ToString().PadLeft(8) + " " + perm_inv[i].ToString().PadLeft(8) + ""); } break; } } // // Compute the bandwidth of the permuted array. // bandwidth = AdjacencyMatrix.adj_perm_bandwidth(node_num, adj_num, adj_row, adj, perm, perm_inv); Console.WriteLine(""); Console.WriteLine(" ADJ bandwidth after RCM permutation = " + bandwidth + ""); // // Permute the nodes in NODE_XYZ. // int base_internal = 0; typeMethods.r8col_permute(dim_num, node_num, perm, base_internal, node_xyz); // // Permute the node indices in ELEMENT_NODE. // for (j = 0; j < element_num; j++) { for (i = 0; i < element_order; i++) { int node = element_node[i + j * element_order]; element_node[i + j * element_order] = perm_inv[node]; } } switch (base_user) { // // If the user base was 1, restore it! // case 1: { for (i = 0; i < element_num; i++) { for (j = 0; j < element_order; j++) { element_node[i + j * element_order] += 1; } } Console.WriteLine(""); Console.WriteLine(" Output files will use the same 1-based ordering used by the input."); break; } } // // Write the node and element data. // typeMethods.r8mat_write(node_rcm_filename, dim_num, node_num, node_xyz); Console.WriteLine(""); Console.WriteLine(" Created the file \"" + node_rcm_filename + "\"."); typeMethods.i4mat_write(element_rcm_filename, element_order, element_num, element_node); Console.WriteLine(" Created the file \"" + element_rcm_filename + "\"."); Console.WriteLine(""); Console.WriteLine("TET_MESH_RCM:"); Console.WriteLine(" Normal end of execution."); Console.WriteLine(""); }