void Dump_Maps(const INT *node_map, const INT *elmt_map, ExoII_Read<INT>& file1) { size_t ijk; std::cout << "\n=== node number map (file1 -> file2) local ids\n"; bool one_to_one = true; for (ijk = 0; ijk < file1.Num_Nodes(); ++ijk) { if ((INT)ijk != node_map[ijk]) { one_to_one = false; break; } } if (!one_to_one) { for (ijk = 0; ijk < file1.Num_Nodes(); ++ijk) std::cout << (ijk+1) << " -> " << (node_map[ijk]+1) << "\n"; } else { std::cout << " *** Node map is one-to-one\n"; } std::cout << "\n=== element number map (file1 -> file2) local ids\n"; one_to_one = true; for (ijk = 0; ijk < file1.Num_Elmts(); ++ijk) { if ((INT)ijk != elmt_map[ijk]) { one_to_one = false; break; } } if (!one_to_one) { for (ijk = 0; ijk < file1.Num_Elmts(); ++ijk) std::cout << (ijk+1) << " -> " << (elmt_map[ijk]+1) << "\n"; } else { std::cout << " *** Element map is one-to-one\n"; } std::cout << "===" << std::endl; }
bool Check_Maps(const INT *node_map, const INT *elmt_map, const ExoII_Read<INT>& file1, const ExoII_Read<INT>& file2) { if (file1.Num_Nodes() != file2.Num_Nodes()) { return false; } if (file1.Num_Elmts() != file2.Num_Elmts()) { return false; } if (node_map != nullptr) { for (size_t ijk = 0; ijk < file1.Num_Nodes(); ++ijk) { if ((INT)ijk != node_map[ijk]) { return false; } } } if (elmt_map != nullptr) { for (size_t ijk = 0; ijk < file1.Num_Elmts(); ++ijk) { if ((INT)ijk != elmt_map[ijk]) { return false; } } } // All maps are one-to-one; Don't need to map nodes or elements... return true; }
template <typename INT> bool Check_Global(ExoII_Read<INT> &file1, ExoII_Read<INT> &file2) { bool is_same = true; if (file1.Dimension() != file2.Dimension()) { ERROR(".. Dimension doesn't agree.\n"); is_same = false; } if (file1.Num_Nodes() != file2.Num_Nodes()) { if (interface.map_flag != PARTIAL) { ERROR(".. Number of nodes doesn't agree.\n"); is_same = false; } } if (file1.Num_Elmts() != file2.Num_Elmts()) { if (interface.map_flag != PARTIAL) { ERROR(".. Number of elements doesn't agree.\n"); is_same = false; } } if (file1.Num_Elmt_Blocks() != file2.Num_Elmt_Blocks()) { if (interface.map_flag != PARTIAL) { ERROR(".. Number of element blocks doesn't agree.\n"); is_same = false; } } if (file1.Num_Times() != file2.Num_Times() && !interface.quiet_flag) { ERROR(".. First file has " << file1.Num_Times() << " result times while the second file has " << file2.Num_Times() << ".\n"); } return is_same; }
bool Check_Global(ExoII_Read<INT>& file1, ExoII_Read<INT>& file2) { bool is_same = true; if (file1.Dimension() != file2.Dimension()) { std::cout << "exodiff: ERROR .. Dimension doesn't agree." << std::endl; is_same = false; } if (file1.Num_Nodes() != file2.Num_Nodes()) { if(interface.map_flag != PARTIAL){ std::cout << "exodiff: ERROR .. Number of nodes doesn't agree." << std::endl; is_same = false; } } if (file1.Num_Elmts() != file2.Num_Elmts()) { if(interface.map_flag != PARTIAL){ std::cout << "exodiff: ERROR .. Number of elements doesn't agree." << std::endl; is_same = false; } } if (file1.Num_Elmt_Blocks() != file2.Num_Elmt_Blocks()) { if(interface.map_flag != PARTIAL){ std::cout << "exodiff: ERROR .. Number of element blocks doesn't agree." << std::endl; is_same = false; } } if (file1.Num_Times() != file2.Num_Times() && !interface.quiet_flag) { std::cout << "exodiff: WARNING .. First file has " << file1.Num_Times() << " result times while the second file has " << file2.Num_Times() << ".\n"; } return is_same; }
void Compute_FileId_Maps(INT *&node_map, INT *&elmt_map, ExoII_Read<INT> &file1, ExoII_Read<INT> &file2) { // Compute map of nodes and elements in file1 to nodes and elements in file2 // Use the internal exodus node and element number maps in file1 and file2 to // do the matching. Currently assume (and verify) that number of nodes and // elements match in the two files. SMART_ASSERT(file1.Open()); SMART_ASSERT(file2.Open()); { size_t num_nodes = file1.Num_Nodes(); SMART_ASSERT(num_nodes == file2.Num_Nodes()); node_map = new INT[num_nodes]; SMART_ASSERT(node_map != nullptr); file1.Load_Node_Map(); file2.Load_Node_Map(); const INT *node_id_map1 = file1.Get_Node_Map(); const INT *node_id_map2 = file2.Get_Node_Map(); if (!internal_compute_maps(node_map, node_id_map1, node_id_map2, num_nodes, "node")) { delete[] node_map; node_map = nullptr; } } { size_t num_elmts = file1.Num_Elmts(); SMART_ASSERT(num_elmts == file2.Num_Elmts()); elmt_map = new INT[num_elmts]; SMART_ASSERT(elmt_map != nullptr); file1.Load_Elmt_Map(); file2.Load_Elmt_Map(); const INT *elem_id_map1 = file1.Get_Elmt_Map(); const INT *elem_id_map2 = file2.Get_Elmt_Map(); if (!internal_compute_maps(elmt_map, elem_id_map1, elem_id_map2, num_elmts, "element")) { delete[] elmt_map; elmt_map = nullptr; } } }
bool Check_Global(ExoII_Read& file1, ExoII_Read& file2) { bool is_same = true; if (file1.Dimension() != file2.Dimension()) { std::cout << "exodiff: ERROR .. Dimension doesn't agree." << std::endl; is_same = false; } if (file1.Num_Nodes() != file2.Num_Nodes()) { if(specs.map_flag != PARTIAL){ std::cout << "exodiff: ERROR .. Number of nodes don't agree." << std::endl; is_same = false; } } if (file1.Num_Elmts() != file2.Num_Elmts()) { if(specs.map_flag != PARTIAL){ std::cout << "exodiff: ERROR .. Number of elements don't agree." << std::endl; is_same = false; } } if (!specs.map_flag && file1.Num_Elmt_Blocks() != file2.Num_Elmt_Blocks()) { if(specs.map_flag != PARTIAL){ std::cout << "exodiff: ERROR .. Number of blocks don't agree." << std::endl; is_same = false; } } if (!specs.map_flag && file1.Num_Times() != file2.Num_Times() && !specs.quiet_flag) { std::cout << "exodiff: WARNING First file has " << file1.Num_Times() << " result times while the second file has " << file2.Num_Times() << ".\n" << " Will consider only " << (file1.Num_Times() < file2.Num_Times() ? file1.Num_Times() : file2.Num_Times()) << " timesteps." << std::endl; } return is_same; }
double Find_Min_Coord_Sep(ExoII_Read<INT>& file) { size_t num_nodes = file.Num_Nodes(); if (num_nodes < 2) return 0.0; file.Load_Nodal_Coordinates(); const double* x = (double*)file.X_Coords(); const double* y = (double*)file.Y_Coords(); const double* z = (double*)file.Z_Coords(); auto indx = new INT[num_nodes]; for (size_t i=0; i < num_nodes; i++) { indx[i] = i; } // Find coordinate with largest range... const double *r = x; double range = find_range(x, num_nodes); if (file.Dimension() > 1) { double yrange = find_range(y, num_nodes); if (yrange > range) { range = yrange; r = y; } } if (file.Dimension() > 2) { double zrange = find_range(z, num_nodes); if (zrange > range) { range = zrange; r = z; } } // Sort based on coordinate with largest range... index_qsort(r, indx, num_nodes); double min = DBL_MAX;; switch (file.Dimension()) { case 1: { for (size_t i=0; i < num_nodes; i++) { for (size_t j=i+1; j < num_nodes; j++) { double tmp = dist_sqrd(x[indx[i]], x[indx[j]]); if (tmp >= min) { break; } else { min = tmp; } } } break; } case 2: { for (size_t i=0; i < num_nodes; i++) { for (size_t j=i+1; j < num_nodes; j++) { double delr = dist_sqrd(r[indx[i]], r[indx[j]]); if (delr > min) { break; } else { double tmp = dist_sqrd(x[indx[i]], y[indx[i]], x[indx[j]], y[indx[j]]); min = min < tmp ? min : tmp; } } } break; } case 3: { for (size_t i=0; i < num_nodes; i++) { for (size_t j=i+1; j < num_nodes; j++) { double delr = dist_sqrd(r[indx[i]], r[indx[j]]); if (delr > min) { break; } else { double tmp = dist_sqrd(x[indx[i]], y[indx[i]], z[indx[i]], x[indx[j]], y[indx[j]], z[indx[j]]); min = min < tmp ? min : tmp; } } } break; } } delete [] indx; return sqrt(min); }
void Compute_Maps(INT*& node_map, INT*& elmt_map, ExoII_Read<INT>& file1, ExoII_Read<INT>& file2) { SMART_ASSERT(file1.Open()); SMART_ASSERT(file2.Open()); size_t num_nodes = file1.Num_Nodes(); size_t num_elmts = file1.Num_Elmts(); int dim = file1.Dimension(); // ******************** elements ******************** // // Load global ids (0-offset) into id array. auto id = new INT[num_elmts]; {for (size_t e = 0; e < num_elmts; ++e) id[e] = e;} // Get map storage. node_map = new INT[num_nodes]; SMART_ASSERT(node_map != nullptr); {for (size_t i = 0; i < num_nodes; ++i) node_map[i] = -1; } elmt_map = new INT[num_elmts]; SMART_ASSERT(elmt_map != nullptr); // Create storage for midpoints. double *x2 = nullptr, *y2 = nullptr, *z2 = nullptr; x2 = new double[num_elmts]; SMART_ASSERT(x2 != nullptr); if (dim > 1) { y2 = new double[num_elmts]; SMART_ASSERT(y2 != nullptr); } if (dim > 2) { z2 = new double[num_elmts]; SMART_ASSERT(z2 != nullptr); } // Load coordinates for file 2 and get pointers to them. file2.Load_Nodal_Coordinates(); const double* x2_f = (double*)file2.X_Coords(); const double* y2_f = (double*)file2.Y_Coords(); const double* z2_f = (double*)file2.Z_Coords(); // Load connectivities for all blocks in second file. file2.Load_Elmt_Block_Descriptions(); { // Compute midpoints of each element and place into x,y,z arrays. size_t num_blocks = file2.Num_Elmt_Blocks(), num_elmts_in_block, num_nodes_per_elmt, e = 0; double sum_x, sum_y, sum_z; for (size_t b = 0; b < num_blocks; ++b) { const Exo_Block<INT>* block = file2.Get_Elmt_Block_by_Index(b); num_elmts_in_block = block->Size(); num_nodes_per_elmt = block->Num_Nodes_per_Elmt(); for (size_t i = 0; i < num_elmts_in_block; ++i) { const INT* conn = block->Connectivity(i); // Connectivity for element i. sum_x = 0.0; sum_y = 0.0; sum_z = 0.0; for (size_t j = 0; j < num_nodes_per_elmt; ++j) { sum_x += x2_f[ conn[j] - 1 ]; if (dim > 1) sum_y += y2_f[ conn[j] - 1 ]; if (dim > 2) sum_z += z2_f[ conn[j] - 1 ]; } x2[e] = sum_x / (double)num_nodes_per_elmt; if (dim > 1) y2[e] = sum_y / (double)num_nodes_per_elmt; if (dim > 2) z2[e] = sum_z / (double)num_nodes_per_elmt; ++e; } } } // Sort by x value. index_qsort(x2, id, num_elmts); #if 0 std::cout << "****************** elmts ******************** " << std::endl; {for (size_t i = 0; i < num_elmts; ++i) std::cout << i << ")\t" << x2[id[i]] << "\t" << y2[id[i]] << "\t" << z2[id[i]] << "\t" << id[i] << std::endl;} std::cout << "****************** elmts ******************** " << std::endl; #endif // Load and get nodal coordinates for first file. file1.Load_Nodal_Coordinates(); const double* x1_f = (double*)file1.X_Coords(); const double* y1_f = (double*)file1.Y_Coords(); const double* z1_f = (double*)file1.Z_Coords(); // Cannot ignore the comparisons, so make sure the coord_tol_type // is not -1 which is "ignore" TOLERANCE_TYPE_enum save_tolerance_type = interface.coord_tol.type; if (save_tolerance_type == IGNORE) interface.coord_tol.type = ABSOLUTE; // Match elmts in first file to their corresponding elmts in second. size_t num_blocks = file1.Num_Elmt_Blocks(); size_t num_elmts_in_block; size_t num_nodes_per_elmt; size_t e1 = 0; size_t e2 = 0; INT sort_idx; double mid_x, mid_y, mid_z; for (size_t b = 0; b < num_blocks; ++b) { const Exo_Block<INT>* block1 = file1.Get_Elmt_Block_by_Index(b); file1.Load_Elmt_Block_Description(b); num_elmts_in_block = block1->Size(); num_nodes_per_elmt = block1->Num_Nodes_per_Elmt(); for (size_t i = 0; i < num_elmts_in_block; ++i) { // Connectivity for element i. const INT* conn1 = block1->Connectivity(i); // Compute midpoint. mid_x = 0.0; mid_y = 0.0; mid_z = 0.0; for (size_t j = 0; j < num_nodes_per_elmt; ++j) { SMART_ASSERT(conn1[j] >= 1 && conn1[j] <= (INT)num_nodes); mid_x += x1_f[conn1[j]-1]; if (dim > 1) mid_y += y1_f[conn1[j]-1]; if (dim > 2) mid_z += z1_f[conn1[j]-1]; } mid_x /= (double)num_nodes_per_elmt; if (dim > 1) mid_y /= (double)num_nodes_per_elmt; if (dim > 2) mid_z /= (double)num_nodes_per_elmt; // Locate midpoint in sorted array. sort_idx = Find(mid_x, mid_y, mid_z, x2, y2, z2, id, num_elmts, dim, file1.Block_Id(b), interface.ignore_dups); if (sort_idx < 0) { std::cout << "\nexodiff: ERROR: Files are different (couldn't match element " << (i+1) << " from block " << file1.Block_Id(b) << " from first file to second)" << std::endl; exit(1); } e2 = id[sort_idx]; // Assign element map for this element. elmt_map[e1] = e2; { // Determine the block and elmt index of matched element. int b2; size_t l2; file2.Global_to_Block_Local(e2+1, b2, l2); const Exo_Block<INT>* block2 = file2.Get_Elmt_Block_by_Index(b2); SMART_ASSERT(block2 != nullptr); // Check that the element types are the same. if (num_nodes_per_elmt != block2->Num_Nodes_per_Elmt()) { std::cout << "\nexodiff: ERROR: Files are different.\n" << " In File 1: Element " << (i+1) << " in Block " << file1.Block_Id(b) << " has " << num_nodes_per_elmt << " and\n" << " In File 2: Element " << (l2+1) << " in Block " << file2.Block_Id(b2) << " has " << block2->Num_Nodes_per_Elmt() << std::endl; exit(1); } // Get connectivity for file2 element. const INT* conn2 = block2->Connectivity(l2); // Match each node in the first elmt with a node in the second // and assign node_map. for (size_t ln1 = 0; ln1 < num_nodes_per_elmt; ++ln1) { // Grab coordinate of node in first file. double x1_val = x1_f[ conn1[ln1] - 1 ]; double y1_val = dim > 1 ? y1_f[ conn1[ln1] - 1 ] : 0.0; double z1_val = dim > 2 ? z1_f[ conn1[ln1] - 1 ] : 0.0; size_t found = 0; for (size_t ln2 = 0; ln2 < num_nodes_per_elmt; ++ln2) { // Grab coordinate of node in second file. double x2_val = x2_f[ conn2[ln2] - 1 ]; double y2_val = dim > 1 ? y2_f[ conn2[ln2] - 1 ] : 0.0; double z2_val = dim > 2 ? z2_f[ conn2[ln2] - 1 ] : 0.0; if (!interface.coord_tol.Diff(x1_val, x2_val) && !interface.coord_tol.Diff(y1_val, y2_val) && !interface.coord_tol.Diff(z1_val, z2_val) ) { // assert that if this node has been given a map // previously, that it agrees with the latest // assignment. if (node_map[conn1[ln1]-1] >= 0 && node_map[conn1[ln1]-1] != conn2[ln2]-1) { if (!interface.ignore_dups) { // Node in file 1. INT node1 = conn1[ln1]; double x1a = x1_f[node1-1]; double y1a = dim >= 2 ? y1_f[node1-1] : 0.0; double z1a = dim >= 3 ? z1_f[node1-1] : 0.0; // Node in file 2 that was already mapped to node 1 in file 1 INT n1 = node_map[conn1[ln1]-1]+1; double x2a = x2_f[n1-1]; double y2a = dim >= 2 ? y2_f[n1-1] : 0.0; double z2a = dim >= 3 ? z2_f[n1-1] : 0.0; // Node in file 2 that is now being mapped to node 1 in file 1 INT n2 = conn2[ln2]; double x2b = x2_f[n2-1]; double y2b = dim >= 2 ? y2_f[n2-1] : 0.0; double z2b = dim >= 3 ? z2_f[n2-1] : 0.0; SMART_ASSERT(!interface.coord_tol.Diff(x2a, x2b) && !interface.coord_tol.Diff(y2a, y2b) && !interface.coord_tol.Diff(z2a, z2b)); std::cout << "\nexodiff: ERROR - No unique node mapping possible.\n" << "\tFile 1, Node " << node1 << " at (" << x1a << ", " << y1a << ", " << z1a << ") maps to both:\n" << "\tFile 2, Node " << n1 << " at (" << x2a << ", " << y2a << ", " << z2a << ") and\n" << "\tFile 2, Node " << n2 << " at (" << x2b << ", " << y2b << ", " << z2b << ")\n\n"; exit(1); } found = 1; break; } node_map[ conn1[ln1] - 1 ] = conn2[ln2] - 1; found = 1; break; } } if (!found) { std::cout << "\nexodiff: ERROR: Cannot find a match for node at position " << ln1+1 << " in first element.\n" << "\tFile 1: Element " << (i+1) << " in Block " << file1.Block_Id(b) << " nodes:\n"; for (size_t l1 = 0; l1 < num_nodes_per_elmt; ++l1) { double x_val = x1_f[ conn1[l1] - 1 ]; double y_val = dim > 1 ? y1_f[ conn1[l1] - 1 ] : 0.0; double z_val = dim > 2 ? z1_f[ conn1[l1] - 1 ] : 0.0; std::cout << "\t(" << l1+1 << ")\t" << conn1[l1] << "\t" << std::setprecision(9) << x_val << "\t" << y_val << "\t" << z_val << "\n"; } std::cout << "\tFile 2: Element " << (l2+1) << " in Block " << file1.Block_Id(b) << " nodes:\n"; for (size_t l3 = 0; l3 < num_nodes_per_elmt; ++l3) { double x_val = x2_f[ conn2[l3] - 1 ]; double y_val = dim > 1 ? y2_f[ conn2[l3] - 1 ] : 0.0; double z_val = dim > 2 ? z2_f[ conn2[l3] - 1 ] : 0.0; std::cout << "\t(" << l3+1 << ")\t" << conn2[l3] << "\t" << std::setprecision(9) << x_val << "\t" << y_val << "\t" << z_val << "\n"; } std::cout << "Coordinates compared using tolerance: " << interface.coord_tol.value << " (" << interface.coord_tol.typestr() << "), floor: " << interface.coord_tol.floor << "\n"; exit(1); } } // End of local node loop on file1's element. } // End of local node search block. ++e1; } // End of loop on elements in file1 element block. file1.Free_Elmt_Block(b); } // End of loop on file1 blocks. // Check that all nodes in the file have been matched... If any // unmatched nodes are found, then perform a node-based matching // algorithm... for (size_t i=0; i < num_nodes; i++) { if (node_map[i] < 0) { Compute_Node_Map(node_map, file1, file2); break; } } file1.Free_Nodal_Coordinates(); file2.Free_Nodal_Coordinates(); file2.Free_Elmt_Blocks(); if (x2 != nullptr) delete [] x2; if (y2 != nullptr) delete [] y2; if (z2 != nullptr) delete [] z2; if (id != nullptr) delete [] id; interface.coord_tol.type = save_tolerance_type; }
void Compute_Partial_Maps(INT*& node_map, INT*& elmt_map, ExoII_Read<INT>& file1, ExoII_Read<INT>& file2) { SMART_ASSERT(file1.Open()); SMART_ASSERT(file2.Open()); size_t num_nodes1 = file1.Num_Nodes(); size_t num_elmts1 = file1.Num_Elmts(); //size_t num_nodes2 = file2.Num_Nodes(); size_t num_elmts2 = file2.Num_Elmts(); int dim = file1.Dimension(); SMART_ASSERT(dim == file2.Dimension()); // ******************** elements ******************** // // Load global ids (0-offset) into id array. auto id2 = new INT[num_elmts2]; {for (size_t e = 0; e < num_elmts2; ++e) id2[e] = e;} // Get map storage. node_map = new INT[num_nodes1]; SMART_ASSERT(node_map != nullptr); {for (size_t i = 0; i < num_nodes1; ++i) node_map[i] = -1; } elmt_map = new INT[num_elmts1]; SMART_ASSERT(elmt_map != nullptr); {for (size_t i = 0; i < num_elmts1; ++i) elmt_map[i] = -1; } // Create storage for midpoints. double *x2 = nullptr, *y2 = nullptr, *z2 = nullptr; x2 = new double[num_elmts2]; SMART_ASSERT(x2 != nullptr); if (dim > 1) { y2 = new double[num_elmts2]; SMART_ASSERT(y2 != nullptr); } if (dim > 2) { z2 = new double[num_elmts2]; SMART_ASSERT(z2 != nullptr); } // Load coordinates for file 2 and get pointers to them. file2.Load_Nodal_Coordinates(); const double* x2_f = (double*)file2.X_Coords(); const double* y2_f = (double*)file2.Y_Coords(); const double* z2_f = (double*)file2.Z_Coords(); // Load connectivities for all blocks in second file. file2.Load_Elmt_Block_Descriptions(); { // Compute midpoints of each element and place into x,y,z arrays. size_t num_blocks2 = file2.Num_Elmt_Blocks(), num_elmts_in_block, num_nodes_per_elmt, e = 0; double sum_x, sum_y, sum_z; for (size_t b = 0; b < num_blocks2; ++b) { const Exo_Block<INT>* block = file2.Get_Elmt_Block_by_Index(b); num_elmts_in_block = block->Size(); num_nodes_per_elmt = block->Num_Nodes_per_Elmt(); for (size_t i = 0; i < num_elmts_in_block; ++i) { const INT* conn = block->Connectivity(i); // Connectivity for element i. sum_x = 0.0; sum_y = 0.0; sum_z = 0.0; for (size_t j = 0; j < num_nodes_per_elmt; ++j) { sum_x += x2_f[ conn[j] - 1 ]; if (dim > 1) sum_y += y2_f[ conn[j] - 1 ]; if (dim > 2) sum_z += z2_f[ conn[j] - 1 ]; } x2[e] = sum_x / (double)num_nodes_per_elmt; if (dim > 1) y2[e] = sum_y / (double)num_nodes_per_elmt; if (dim > 2) z2[e] = sum_z / (double)num_nodes_per_elmt; ++e; } } } // Sort by x value. index_qsort(x2, id2, num_elmts2); #if 0 std::cout << "****************** elmts ******************** " << std::endl; {for (size_t i = 0; i < num_elmts; ++i) std::cout << i << ")\t" << x2[id[i]] << "\t" << y2[id[i]] << "\t" << z2[id[i]] << "\t" << id[i] << std::endl;} std::cout << "****************** elmts ******************** " << std::endl; #endif // Load and get nodal coordinates for first file. file1.Load_Nodal_Coordinates(); const double* x1_f = (double*)file1.X_Coords(); const double* y1_f = (double*)file1.Y_Coords(); const double* z1_f = (double*)file1.Z_Coords(); // Cannot ignore the comparisons, so make sure the coord_tol_type // is not -1 which is "ignore" TOLERANCE_TYPE_enum save_tolerance_type = interface.coord_tol.type; if (save_tolerance_type == IGNORE) interface.coord_tol.type = ABSOLUTE; // Match elmts in first file to their corresponding elmts in second. size_t num_blocks1 = file1.Num_Elmt_Blocks(); size_t num_elmts_in_block; size_t num_nodes_per_elmt; size_t e1 = 0; size_t e2 = 0; INT sort_idx; double mid_x, mid_y, mid_z; bool first = true; size_t unmatched = 0; for (size_t b = 0; b < num_blocks1; ++b) { const Exo_Block<INT>* block1 = file1.Get_Elmt_Block_by_Index(b); file1.Load_Elmt_Block_Description(b); num_elmts_in_block = block1->Size(); num_nodes_per_elmt = block1->Num_Nodes_per_Elmt(); for (size_t i = 0; i < num_elmts_in_block; ++i) { // Connectivity for element i. const INT* conn1 = block1->Connectivity(i); // Compute midpoint. mid_x = 0.0; mid_y = 0.0; mid_z = 0.0; for (size_t j = 0; j < num_nodes_per_elmt; ++j) { SMART_ASSERT(conn1[j] >= 1 && conn1[j] <= (INT)num_nodes1); mid_x += x1_f[conn1[j]-1]; if (dim > 1) mid_y += y1_f[conn1[j]-1]; if (dim > 2) mid_z += z1_f[conn1[j]-1]; } mid_x /= (double)num_nodes_per_elmt; if (dim > 1) mid_y /= (double)num_nodes_per_elmt; if (dim > 2) mid_z /= (double)num_nodes_per_elmt; // Locate midpoint in sorted array. sort_idx = Find(mid_x, mid_y, mid_z, x2, y2, z2, id2, num_elmts2, dim, file1.Block_Id(b), interface.ignore_dups); if (sort_idx < 0) { unmatched++; if (first && interface.show_unmatched) { std::cout << "exodiff: Doing Partial Comparison: No Match for (b.e):\n"; } first = false; if (interface.show_unmatched) std::cout << file1.Block_Id(b) << "." << (i+1) << ", "; } else{ e2 = id2[sort_idx]; elmt_map[e1] = e2; // Assign element map for this element. // Determine the block and elmt index of matched element. int b2; size_t l2; file2.Global_to_Block_Local(e2+1, b2, l2); const Exo_Block<INT>* block2 = file2.Get_Elmt_Block_by_Index(b2); SMART_ASSERT(block2 != nullptr); // Check that the element types are the same. if (num_nodes_per_elmt != block2->Num_Nodes_per_Elmt()) { std::cout << "\nexodiff: ERROR: Files are different.\n" << " In File 1: Element " << (i+1) << " in Block " << file1.Block_Id(b) << " has " << num_nodes_per_elmt << " and\n" << " In File 2: Element " << (l2+1) << " in Block " << file2.Block_Id(b2) << " has " << block2->Num_Nodes_per_Elmt() << std::endl; exit(1); } // Get connectivity for file2 element. const INT* conn2 = block2->Connectivity(l2); // Match each node in the first elmt with a node in the second // and assign node_map. for (size_t ln1 = 0; ln1 < num_nodes_per_elmt; ++ln1) { // Grab coordinate of node in first file. double x1_val = x1_f[ conn1[ln1] - 1 ]; double y1_val = dim > 1 ? y1_f[ conn1[ln1] - 1 ] : 0.0; double z1_val = dim > 2 ? z1_f[ conn1[ln1] - 1 ] : 0.0; size_t found = 0; for (size_t ln2 = 0; ln2 < num_nodes_per_elmt; ++ln2) { // Grab coordinate of node in second file. double x2_val = x2_f[ conn2[ln2] - 1 ]; double y2_val = dim > 1 ? y2_f[ conn2[ln2] - 1 ] : 0.0; double z2_val = dim > 2 ? z2_f[ conn2[ln2] - 1 ] : 0.0; if (!interface.coord_tol.Diff(x1_val, x2_val) && !interface.coord_tol.Diff(y1_val, y2_val) && !interface.coord_tol.Diff(z1_val, z2_val) ) { node_map[ conn1[ln1] - 1 ] = conn2[ln2] - 1; found = 1; break; } } if (!found) { std::cout << "\nexodiff: ERROR: Cannot find a match for node at position " << ln1+1 << " in first element.\n" << "\tFile 1: Element " << (i+1) << " in Block " << file1.Block_Id(b) << " nodes:\n"; for (size_t l1 = 0; l1 < num_nodes_per_elmt; ++l1) { double x_val = x1_f[ conn1[l1] - 1 ]; double y_val = dim > 1 ? y1_f[ conn1[l1] - 1 ] : 0.0; double z_val = dim > 2 ? z1_f[ conn1[l1] - 1 ] : 0.0; std::cout << "\t(" << l1+1 << ")\t" << conn1[l1] << "\t" << std::setprecision(9) << x_val << "\t" << y_val << "\t" << z_val << "\n"; } std::cout << "\tFile 2: Element " << (l2+1) << " in Block " << file1.Block_Id(b) << " nodes:\n"; for (size_t l3 = 0; l3 < num_nodes_per_elmt; ++l3) { double x_val = x2_f[ conn2[l3] - 1 ]; double y_val = dim > 1 ? y2_f[ conn2[l3] - 1 ] : 0.0; double z_val = dim > 2 ? z2_f[ conn2[l3] - 1 ] : 0.0; std::cout << "\t(" << l3+1 << ")\t" << conn2[l3] << "\t" << std::setprecision(9) << x_val << "\t" << y_val << "\t" << z_val << "\n"; } std::cout << "Coordinates compared using tolerance: " << interface.coord_tol.value << " (" << interface.coord_tol.typestr() << "), floor: " << interface.coord_tol.floor << "\n"; exit(1); } } // End of local node loop on file1's element. } // End of local node search block. ++e1; } // End of loop on elements in file1 element block. file1.Free_Elmt_Block(b); } // End of loop on file1 blocks. if (!first) { std::cout << "\nPartial Map selected -- " << unmatched << " elements unmatched\n"; } else { if (num_elmts1 == num_elmts2) std::cout << "exodiff: INFO .. Partial Map was specfied, but not needed. All elements matched.\n"; } // Check that all nodes in the file have been matched... If any // unmatched nodes are found, then perform a node-based matching // algorithm... // for (size_t i=0; i < num_nodes; i++) { // if (node_map[i] < 0) { // Compute_Node_Map(node_map, file1, file2); // break; // } // } file1.Free_Nodal_Coordinates(); file2.Free_Nodal_Coordinates(); file2.Free_Elmt_Blocks(); if (x2 != nullptr) delete [] x2; if (y2 != nullptr) delete [] y2; if (z2 != nullptr) delete [] z2; if (id2 != nullptr) delete [] id2; interface.coord_tol.type = save_tolerance_type; }
bool Compare_Maps(ExoII_Read<INT>& file1, ExoII_Read<INT>& file2, const INT *node_map, const INT *elmt_map, bool partial_flag) { // Check whether the node and element number maps from both file1 // and file2 match which indicates that we are comparing the same // element and node in each file. size_t num_nodes1 = file1.Num_Nodes(); size_t num_elmts1 = file1.Num_Elmts(); //size_t num_nodes2 = file2.Num_Nodes(); //size_t num_elmts2 = file2.Num_Elmts(); // NOTE: file1 maps are already loaded... file2.Load_Node_Map(); file2.Load_Elmt_Map(); const INT *node_id_map1 = file1.Get_Node_Map(); const INT *elem_id_map1 = file1.Get_Elmt_Map(); const INT *node_id_map2 = file2.Get_Node_Map(); const INT *elem_id_map2 = file2.Get_Elmt_Map(); bool diff = false; size_t warn_count = 0; if (node_map != nullptr) { // There is a map between file1 and file2, but all nodes are // used in both files. for (size_t i=0; i < num_nodes1; i++) { if (node_id_map1[i] != node_id_map2[node_map[i]]) { if (!(node_id_map2[node_map[i]] == 0 && partial_flag)) { // Don't output diff if non-matched and partial std::cout << "exodiff: WARNING .. The local node " << i+1 << " with global id " << node_id_map1[i] << " in file1 has the global id " << node_id_map2[node_map[i]] << " in file2.\n"; diff = true; warn_count++; if (warn_count > 100) { std::cout << "exodiff: WARNING .. Too many warnings, skipping remainder...\n"; break; } } } } } else { // No node mapping between file1 and file2 -- do a straight compare. for (size_t i=0; i < num_nodes1; i++) { if (node_id_map1[i] != node_id_map2[i]) { if (!(node_id_map2[i] == 0 && partial_flag)) { // Don't output diff if non-matched and partial std::cout << "exodiff: WARNING .. The local node " << i+1 << " with global id " << node_id_map1[i] << " in file1 has the global id " << node_id_map2[i] << " in file2.\n"; diff = true; warn_count++; if (warn_count > 100) { std::cout << "exodiff: WARNING .. Too many warnings, skipping remainder...\n"; break; } } } } } warn_count = 0; if (elmt_map != nullptr) { // There is a map between file1 and file2, but all elements are // used in both files. for (size_t i=0; i < num_elmts1; i++) { if (elem_id_map1[i] != elem_id_map2[elmt_map[i]]) { if (!(elem_id_map2[elmt_map[i]] == 0 && partial_flag)) { // Don't output diff if non-matched and partial std::cout << "exodiff: WARNING .. The local element " << i+1 << " with global id " << elem_id_map1[i] << " in file1 has the global id " << elem_id_map2[elmt_map[i]] << " in file2.\n"; diff = true; warn_count++; if (warn_count > 100) { std::cout << "exodiff: WARNING .. Too many warnings, skipping remainder...\n"; break; } } } } } else { // No element mapping between file1 and file2 -- do a straight compare. for (size_t i=0; i < num_elmts1; i++) { if (elem_id_map1[i] != elem_id_map2[i]) { if (!(elem_id_map2[i] == 0 && partial_flag)) { // Don't output diff if non-matched and partial std::cout << "exodiff: WARNING .. The local element " << i+1 << " with global id " << elem_id_map1[i] << " in file1 has the global id " << elem_id_map2[i] << " in file2.\n"; diff = true; warn_count++; if (warn_count > 100) { std::cout << "exodiff: WARNING .. Too many warnings, skipping remainder...\n"; break; } } } } } file2.Free_Node_Map(); file2.Free_Elmt_Map(); if (diff) std::cout << std::endl; return diff; }