void build_local_element_map(RegionVector &part_mesh, std::vector<INT> &local_element_map) { size_t global = 0; size_t offset = 0; for (size_t p = 0; p < part_mesh.size(); p++) { Ioss::ElementBlockContainer ebs = part_mesh[p]->get_element_blocks(); Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); while (i != ebs.end()) { Ioss::ElementBlock *eb = *i++; size_t num_elem = eb->get_property("entity_count").get_int(); if (entity_is_omitted(eb)) { // Fill local_element_map with -1 for the omitted elements. for (size_t j = 0; j < num_elem; j++) { local_element_map[offset+j] = -1; } } else { for (size_t j = 0; j < num_elem; j++) { local_element_map[offset+j] = global++; } } offset += num_elem; } } }
Block::Block(const Ioss::ElementBlock &other) { id = other.get_property("id").get_int(); elementCount = other.get_property("entity_count").get_int(); nodesPerElement = other.get_property("topology_node_count").get_int(); attributeCount = other.get_property("attribute_count").get_int(); offset_ = other.get_offset(); std::string el_type = other.get_property("topology_type").get_string(); if (other.property_exists("original_topology_type")) { el_type = other.get_property("original_topology_type").get_string(); } std::strncpy(elType, el_type.c_str(), MAX_STR_LENGTH); elType[MAX_STR_LENGTH] = 0; // Fixup an exodusII kludge. For triangular elements, the same // name is used for 2D elements and 3D shell elements. Convert // to unambiguous names for the IO Subsystem. The 2D name // stays the same, the 3D name becomes 'trishell#' // Here, we need to map back to the 'triangle' name... if (std::strncmp(elType, "trishell", 8) == 0) std::strncpy(elType, "triangle", 8); std::string io_name = other.name(); std::strncpy(name, io_name.c_str(), MAX_STR_LENGTH); name[MAX_STR_LENGTH] = 0; }
void generate_element_ids(RegionVector &part_mesh, const std::vector<INT> &local_element_map, std::vector<INT> &global_element_map) { // Follow same logic as 'build_local_element_map' to ensure elements // are processed in same order. // Many models do not use the element number map at all, so they // will have a 1..numel map. If all parts have that, then we don't // want to do any fancy duplicate removal and other processing, just // output a 1..numel map for the output mesh... We still generate // the global_element_map, but check whether any of the part blocks // have a non-1..numel map... bool has_map = false; size_t offset = 0; for (size_t p = 0; p < part_mesh.size(); p++) { Ioss::ElementBlockContainer ebs = part_mesh[p]->get_element_blocks(); Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); while (i != ebs.end()) { Ioss::ElementBlock *eb = *i++; INT num_elem = eb->get_property("entity_count").get_int(); if (!entity_is_omitted(eb)) { std::vector<INT> part_ids; eb->get_field_data("ids", part_ids); if (!has_map) { INT eb_offset = eb->get_offset(); for (INT j = 0; j < num_elem; j++) { if (part_ids[j] != eb_offset+j+1) { has_map = true; break; } } } for (INT j = 0; j < num_elem; j++) { INT gpos = local_element_map[offset+j]; if (gpos >= 0) global_element_map[gpos] = part_ids[j]; } } offset += num_elem; } } // Check for duplicates... // NOTE: Used to use an indexed sort here, but if there was a // duplicate id, it didnt really care whether part 1 or part N's // index came first which causes really screwy element maps. // Instead, lets sort a vector containing pairs of <id, index> where // the index will always? increase for increasing part numbers... std::vector<std::pair<INT,INT> > index(global_element_map.size()); for (size_t i=0; i < index.size(); i++) { index[i] = std::make_pair(global_element_map[i],(INT)i); } std::sort(index.begin(), index.end()); INT max_id = index[index.size()-1].first + 1; size_t beg = 0; for (size_t i=1; i < index.size(); i++) { if (index[beg].first == index[i].first) { // Duplicate found... Assign it a new id greater than any // existing id... (What happens if we exceed INT_MAX?) global_element_map[index[i].second] = max_id++; // Keep 'beg' the same in case multiple duplicate of this value. } else { beg = i; } } }