diff --git a/packages/seacas/applications/conjoin/CJ_SystemInterface.C b/packages/seacas/applications/conjoin/CJ_SystemInterface.C index c9935b93c81d..7d2e52dd0648 100644 --- a/packages/seacas/applications/conjoin/CJ_SystemInterface.C +++ b/packages/seacas/applications/conjoin/CJ_SystemInterface.C @@ -62,6 +62,11 @@ void Excn::SystemInterface::enroll_options() options_.enroll("64-bit", GetLongOption::NoValue, "True if forcing the use of 64-bit integers for the output file", nullptr); + options_.enroll("sort_times", GetLongOption::NoValue, + "Sort the input files on the minimum timestep time in the file. " + "Default is to process files in the order they appear on the command line.", + nullptr); + options_.enroll( "compress", GetLongOption::MandatoryValue, "Specify the hdf5 (netcdf4) compression level [0..9] to be used on the output file.", @@ -256,13 +261,12 @@ bool Excn::SystemInterface::parse_options(int argc, char **argv) } } - if (options_.retrieve("netcdf4") != nullptr) { - useNetcdf4_ = true; - } - - if (options_.retrieve("64-bit") != nullptr) { - ints64Bit_ = true; - } + useNetcdf4_ = options_.retrieve("netcdf4") != nullptr; + sortTimes_ = options_.retrieve("sort_times") != nullptr; + ints64Bit_ = options_.retrieve("64-bit") != nullptr; + ignoreCoordinates_ = options_.retrieve("ignore_coordinate_check") != nullptr; + omitNodesets_ = options_.retrieve("omit_nodesets") != nullptr; + omitSidesets_ = options_.retrieve("omit_sidesets") != nullptr; { const char *temp = options_.retrieve("compress"); @@ -271,24 +275,6 @@ bool Excn::SystemInterface::parse_options(int argc, char **argv) } } - if (options_.retrieve("ignore_coordinate_check") != nullptr) { - ignoreCoordinates_ = true; - } - - if (options_.retrieve("omit_nodesets") != nullptr) { - omitNodesets_ = true; - } - else { - omitNodesets_ = false; - } - - if (options_.retrieve("omit_sidesets") != nullptr) { - omitSidesets_ = true; - } - else { - omitSidesets_ = false; - } - if (options_.retrieve("copyright") != nullptr) { fmt::print("{}", copyright("2009-2019")); exit(EXIT_SUCCESS); diff --git a/packages/seacas/applications/conjoin/CJ_SystemInterface.h b/packages/seacas/applications/conjoin/CJ_SystemInterface.h index e7a96fad3e40..43ad6c4c93ec 100644 --- a/packages/seacas/applications/conjoin/CJ_SystemInterface.h +++ b/packages/seacas/applications/conjoin/CJ_SystemInterface.h @@ -1,4 +1,4 @@ -// Copyright(C) 2009-2010-2017 National Technology & Engineering Solutions +// Copyright(C) 2009-2010-2017, 2020 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -54,6 +54,7 @@ namespace Excn { bool ints_64_bit() const { return ints64Bit_; } bool ignore_coordinates() const { return ignoreCoordinates_; } bool use_netcdf4() const { return useNetcdf4_; } + bool sort_times() const { return sortTimes_; } double alive_value() const { return aliveValue_; } @@ -90,6 +91,7 @@ namespace Excn { bool ints64Bit_{false}; bool ignoreCoordinates_{false}; bool useNetcdf4_{false}; + bool sortTimes_{false}; double aliveValue_{-1.0}; double interpartMinimumTimeDelta_{0.0}; diff --git a/packages/seacas/applications/conjoin/CJ_Version.h b/packages/seacas/applications/conjoin/CJ_Version.h index 90431d309236..532cc8a66fce 100644 --- a/packages/seacas/applications/conjoin/CJ_Version.h +++ b/packages/seacas/applications/conjoin/CJ_Version.h @@ -1,4 +1,4 @@ -// Copyright(C) 2009-2010-2017 National Technology & Engineering Solutions +// Copyright(C) 2009-2010-2017, 2020 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -33,8 +33,8 @@ static char const *qainfo[] = { "conjoin", - "2019/12/03", - "1.4.6", + "2020/03/30", + "1.4.7", }; #endif // SEACAS_Version_h diff --git a/packages/seacas/applications/conjoin/Conjoin.C b/packages/seacas/applications/conjoin/Conjoin.C index cc2fcf43f11e..19a488e01cc2 100644 --- a/packages/seacas/applications/conjoin/Conjoin.C +++ b/packages/seacas/applications/conjoin/Conjoin.C @@ -1,4 +1,4 @@ -// Copyright(C) 2009-2010-2017 National Technology & Engineering Solutions +// Copyright(C) 2009-2017, 2020 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -203,6 +203,8 @@ template int conjoin(Excn::SystemInterface &interFace, T /* dummy */, INT /* dummy int */); namespace { + void sort_file_times(StringVector &input_files); + void compress_white_space(char *str); void add_info_record(char *info_record, int size); template void put_mesh_summary(const Excn::Mesh &mesh); @@ -382,6 +384,10 @@ int main(int argc, char *argv[]) int error = 0; + if (interFace.sort_times()) { + sort_file_times(interFace.inputFiles_); + } + if (!Excn::ExodusFile::initialize(interFace)) { fmt::print(stderr, "ERROR: Problem initializing input and/or output files.\n"); exit(EXIT_FAILURE); @@ -3044,4 +3050,38 @@ namespace { } return max_ent; } + + void sort_file_times(StringVector &input_files) + { + // Sort files based on minimum timestep time + std::vector> file_time_name; + file_time_name.reserve(input_files.size()); + for (auto &filename : input_files) { + float version = 0.0; + int cpu_word_size = sizeof(float); + int io_wrd_size = 0; + int exoid = ex_open(filename.c_str(), EX_READ, &cpu_word_size, &io_wrd_size, &version); + if (exoid < 0) { + fmt::print(stderr, "ERROR: Cannot open file '{}'\n", filename); + exit(EXIT_FAILURE); + } + + int nts = ex_inquire_int(exoid, EX_INQ_TIME); + double time = 0.0; + if (nts > 0) { + ex_get_time(exoid, 1, &time); + } + file_time_name.emplace_back(time, filename); + ex_close(exoid); + } + + std::sort(file_time_name.begin(), file_time_name.end()); + input_files.clear(); + input_files.reserve(file_time_name.size()); + + for (const auto &entry : file_time_name) { + input_files.push_back(entry.second); + } + } + } // namespace diff --git a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h index 55ee76a6a89d..463a5b6114e3 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2017 National Technology & Engineering Solutions + * Copyright(C) 1999-2017, 2020 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -116,6 +116,7 @@ namespace Ioss { } const std::string &name() const { return name_; } + const std::string &ss_name() const { return ss_name_.empty() ? name_ : ss_name_; } int64_t id() const { return id_; } int zone() const { return zone_; } int section() const { return section_; } @@ -128,6 +129,7 @@ namespace Ioss { std::vector hasEntities; // T/F if this set exists on processor p std::string name_{}; + std::string ss_name_{}; int64_t id_{0}; int zone_{0}; // Zone of the element block that this set is on int section_{0}; diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C index 475551aa5f12..9fccc375a839 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C @@ -96,55 +96,6 @@ extern char hdf5_access[64]; namespace { - struct ZoneBC - { - ZoneBC(const std::string &bc_name, std::array &point_range) - : name(bc_name), range_beg(point_range[0]), range_end(point_range[1]) - { - } - - std::string name; - cgsize_t range_beg; - cgsize_t range_end; - }; - - std::vector parse_zonebc_sideblocks(int cgns_file_ptr, int base, int zone, - int myProcessor) - { - int num_bc; - CGCHECK(cg_nbocos(cgns_file_ptr, base, zone, &num_bc)); - - std::vector zonebc; - zonebc.reserve(num_bc); - - for (int i = 0; i < num_bc; i++) { - char boco_name[CGNS_MAX_NAME_LENGTH + 1]; - CG_BCType_t boco_type; - CG_PointSetType_t ptset_type; - cgsize_t num_pnts; - cgsize_t normal_list_size; // ignore - CG_DataType_t normal_data_type; // ignore - int num_dataset; // ignore - CGCHECK(cg_boco_info(cgns_file_ptr, base, zone, i + 1, boco_name, &boco_type, &ptset_type, - &num_pnts, nullptr, &normal_list_size, &normal_data_type, &num_dataset)); - - if (num_pnts != 2 || ptset_type != CG_PointRange) { - std::ostringstream errmsg; - fmt::print( - errmsg, - "CGNS: In Zone {}, boundary condition '{}' has a PointSetType of '{}' and {} points.\n" - " The type must be 'PointRange' and there must be 2 points.", - zone, boco_name, cg_PointSetTypeName(ptset_type), num_pnts); - IOSS_ERROR(errmsg); - } - - std::array point_range; - CGCHECK(cg_boco_read(cgns_file_ptr, base, zone, i + 1, point_range.data(), nullptr)); - zonebc.emplace_back(boco_name, point_range); - } - return zonebc; - } - size_t global_to_zone_local_idx(size_t i, const Ioss::Map *block_map, Ioss::Map &nodeMap, bool isParallel) { @@ -1297,8 +1248,8 @@ namespace Iocgns { #if IOSS_DEBUG_OUTPUT fmt::print("Zone {} shares {} nodes with {}\n", zone, npnts, donorname); #endif - std::vector points(npnts); - std::vector donors(npnts); + CGNSIntVector points(npnts); + CGNSIntVector donors(npnts); CGCHECKM(cg_conn_read(get_file_pointer(), base, zone, i + 1, points.data(), donor_datatype, donors.data())); @@ -1340,7 +1291,7 @@ namespace Iocgns { // The BC_t nodes in the ZoneBC_t give the element range for each SideBlock // which can be matched up below with the Elements_t nodes to get contents // of the SideBlocks. - auto zonebc = parse_zonebc_sideblocks(get_file_pointer(), base, zone, myProcessor); + auto zonebc = Utils::parse_zonebc_sideblocks(get_file_pointer(), base, zone, myProcessor); // ======================================================================== // Read the sections and create an element block for the ones that @@ -1559,8 +1510,8 @@ namespace Iocgns { for (auto J = I + 1; J != blocks.end(); J++) { int dzone = (*J)->get_property("zone").get_int(); const auto & J_map = m_globalToBlockLocalNodeMap[dzone]; - std::vector point_list; - std::vector point_list_donor; + CGNSIntVector point_list; + CGNSIntVector point_list_donor; for (size_t i = 0; i < J_map->size(); i++) { auto global = J_map->map()[i + 1]; // See if this global id exists in I_map... @@ -1958,7 +1909,7 @@ namespace Iocgns { Utils::map_cgns_connectivity(eb->topology(), num_to_get, idata); } else { - std::vector connect(element_nodes * num_to_get); + CGNSIntVector connect(element_nodes * num_to_get); CGCHECKM( cg_elements_read(get_file_pointer(), base, zone, sect, connect.data(), nullptr)); if (field.get_type() == Ioss::Field::INT32) { @@ -2286,14 +2237,14 @@ namespace Iocgns { // TODO(gdsjaar): ? Possibly rewrite using cgi_read_int_data so can skip reading element // connectivity int nodes_per_face = sb->topology()->number_nodes(); - std::vector elements(nodes_per_face * num_to_get); // Not needed, but can't skip + CGNSIntVector elements(nodes_per_face * num_to_get); // Not needed, but can't skip // The parent information will be formatted as: // * `num_to_get` parent elements, // * `num_to_get` zeros (other parent element for face, but on boundary so 0) // * `num_to_get` face_on_element // * `num_to_get` zeros (face on other parent element) - std::vector parent(4 * num_to_get); + CGNSIntVector parent(4 * num_to_get); CGCHECKM( cg_elements_read(get_file_pointer(), base, zone, sect, elements.data(), parent.data())); @@ -2609,7 +2560,7 @@ namespace Iocgns { num_to_get, 0, (cgsize_t *)data, §)); } else { - std::vector connect; + CGNSIntVector connect; connect.reserve(element_nodes * num_to_get); if (field.get_type() == Ioss::Field::INT32) { auto *idata = reinterpret_cast(data); @@ -2749,7 +2700,7 @@ namespace Iocgns { for (size_t i = 0; i < block_map->size(); i++) { auto idx = global_to_zone_local_idx(i, block_map, nodeMap, isParallel); - SMART_ASSERT(idx < num_to_get)(i)(idx)(num_to_get); + SMART_ASSERT(idx < (size_t)num_to_get)(i)(idx)(num_to_get); x[i] = rdata[idx * spatial_dim + 0]; if (spatial_dim > 1) { y[i] = rdata[idx * spatial_dim + 1]; @@ -2786,7 +2737,7 @@ namespace Iocgns { for (size_t i = 0; i < block_map->size(); i++) { auto idx = global_to_zone_local_idx(i, block_map, nodeMap, isParallel); - SMART_ASSERT(idx < num_to_get)(i)(idx)(num_to_get); + SMART_ASSERT(idx < (size_t)num_to_get)(i)(idx)(num_to_get); xyz[i] = rdata[idx]; } @@ -2963,9 +2914,6 @@ namespace Iocgns { // Handle the MESH fields required for a CGNS file model. // (The 'genesis' portion) if (field.get_name() == "element_side") { - // Get name from parent sideset... - auto &name = sb->owner()->name(); - CG_ElementType_t type = Utils::map_topology_to_cgns(sb->topology()->name()); int sect = 0; @@ -2978,7 +2926,12 @@ namespace Iocgns { // the data so would have to generate it. This may cause problems // with codes that use the downstream data if they base the BC off // of the nodes instead of the element/side info. - std::vector point_range{cg_start, cg_end}; + // Get name from parent sideset... This is name of the ZoneBC entry + auto &name = sb->owner()->name(); + // This is the name of the BC_t node + auto sb_name = Iocgns::Utils::decompose_sb_name(sb->name()); + + CGNSIntVector point_range{cg_start, cg_end}; CGCHECKM(cg_boco_write(get_file_pointer(), base, zone, name.c_str(), CG_FamilySpecified, CG_PointRange, 2, point_range.data(), §)); CGCHECKM( @@ -2986,13 +2939,13 @@ namespace Iocgns { CGCHECKM(cg_famname_write(name.c_str())); CGCHECKM(cg_boco_gridlocation_write(get_file_pointer(), base, zone, sect, CG_FaceCenter)); - CGCHECKM(cg_section_partial_write(get_file_pointer(), base, zone, name.c_str(), type, + CGCHECKM(cg_section_partial_write(get_file_pointer(), base, zone, sb_name.c_str(), type, cg_start, cg_end, 0, §)); sb->property_update("section", sect); size_t offset = m_zoneOffset[zone - 1]; - std::vector parent(4 * num_to_get); + CGNSIntVector parent(4 * num_to_get); if (field.get_type() == Ioss::Field::INT32) { int * idata = reinterpret_cast(data); diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h index c1d0b5ba13d2..fcef54796574 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2017 National Technology & Engineering Solutions +// Copyright(C) 1999-2017, 2020 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -46,6 +46,7 @@ #include #include // for string +#include #include namespace Ioss { @@ -204,7 +205,7 @@ namespace Iocgns { mutable std::vector m_bcOffset; // The BC Section element offsets in unstructured output. mutable std::vector m_timesteps; - std::vector> m_blockLocalNodeMap; + std::vector m_blockLocalNodeMap; std::map m_zoneNameMap; mutable std::map m_globalToBlockLocalNodeMap; mutable std::map m_boundaryFaces; diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DecompositionData.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DecompositionData.C index 355412e1b6b2..d254382cef75 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DecompositionData.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DecompositionData.C @@ -572,8 +572,8 @@ namespace Iocgns { } #endif // The 'ids' in 'points' and 'donors' will be zone-local 1-based. - std::vector points(npnts); - std::vector donors(npnts); + CGNSIntVector points(npnts); + CGNSIntVector donors(npnts); CGCHECK2(cg_conn_read(filePtr, base, zone, i + 1, points.data(), donor_datatype, donors.data())); @@ -629,6 +629,13 @@ namespace Iocgns { CGCHECK2(cg_nzones(filePtr, base, &num_zones)); for (int zone = 1; zone <= num_zones; zone++) { + // ======================================================================== + // Read the ZoneBC_t node to get list of SideBlocks to define on this zone + // The BC_t nodes in the ZoneBC_t give the element range for each SideBlock + // which can be matched up below with the Elements_t nodes to get contents + // of the SideBlocks. + auto zonebc = Utils::parse_zonebc_sideblocks(filePtr, base, zone, m_decomposition.m_processor); + cgsize_t size[3]; char zone_name[CGNS_MAX_NAME_LENGTH + 1]; CGCHECK2(cg_zone_read(filePtr, base, zone, zone_name, size)); @@ -688,12 +695,29 @@ namespace Iocgns { } else { // This is a boundary-condition -- sideset (?) - std::string ss_name(section_name); + std::string bc_name(section_name); + std::string ss_name; + // Search zonebc (if it exists) for an entry such that the element ranges overlap. + if (!zonebc.empty()) { + size_t i = 0; + for (; i < zonebc.size(); i++) { + if (zonebc[i].range_beg >= el_start && zonebc[i].range_end <= el_end) { + break; + } + } + if (i < zonebc.size()) { + ss_name = zonebc[i].name; + } + } + else { + ss_name = section_name; + } Ioss::SetDecompositionData sset; sset.zone_ = zone; sset.section_ = is; - sset.name_ = ss_name; + sset.name_ = bc_name; + sset.ss_name_ = ss_name; sset.fileCount = num_entity; sset.topologyType = Utils::map_cgns_to_topology_type(e_type); sset.parentBlockIndex = last_blk_location; @@ -749,7 +773,7 @@ namespace Iocgns { int section = block.section_; // Get the connectivity (raw) for this portion of elements... - std::vector connectivity(overlap * element_nodes); + CGNSIntVector connectivity(overlap * element_nodes); INT blk_start = std::max(b_start, p_start) - b_start + 1; INT blk_end = blk_start + overlap - 1; blk_start = blk_start < 0 ? 0 : blk_start; @@ -802,14 +826,14 @@ namespace Iocgns { auto topology = Ioss::ElementTopology::factory(sset.topologyType, true); int nodes_per_face = topology->number_nodes(); - std::vector nodes(nodes_per_face * sset.file_count()); + CGNSIntVector nodes(nodes_per_face * sset.file_count()); // We get: // * num_to_get parent elements, // * num_to_get zeros (other parent element for face, but on boundary so 0) // * num_to_get face_on_element // * num_to_get zeros (face on other parent element) - std::vector parent(4 * sset.file_count()); + CGNSIntVector parent(4 * sset.file_count()); CGCHECK2(cg_elements_read(filePtr, base, sset.zone(), sset.section(), nodes.data(), parent.data())); @@ -1065,9 +1089,9 @@ namespace Iocgns { auto topology = Ioss::ElementTopology::factory(sset.topologyType, true); int nodes_per_face = topology->number_nodes(); - std::vector nodes(nodes_per_face * sset.file_count()); + CGNSIntVector nodes(nodes_per_face * sset.file_count()); - std::vector parent(4 * sset.file_count()); + CGNSIntVector parent(4 * sset.file_count()); CGCHECK2( cg_elements_read(filePtr, base, sset.zone(), sset.section(), nodes.data(), parent.data())); @@ -1084,7 +1108,7 @@ namespace Iocgns { // on this processor, then assume the face is on this processor... // TODO: Should we filter down to just corner nodes? - std::vector face_nodes(sset.entitylist_map.size() * nodes_per_face); + CGNSIntVector face_nodes(sset.entitylist_map.size() * nodes_per_face); communicate_set_data(nodes.data(), face_nodes.data(), sset, nodes_per_face); // Now, iterate the face connectivity vector and find a match in `m_boundaryFaces` @@ -1170,7 +1194,7 @@ namespace Iocgns { bool raw_ids) const { auto blk = m_elementBlocks[blk_seq]; - std::vector file_conn(blk.file_count() * blk.nodesPerEntity); + CGNSIntVector file_conn(blk.file_count() * blk.nodesPerEntity); int base = 1; CGCHECK2(cgp_elements_read_data(filePtr, base, blk.zone(), blk.section(), blk.fileSectionOffset, blk.fileSectionOffset + blk.file_count() - 1, diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Defines.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Defines.h index 6775e5f9700d..f8e06a502cf3 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Defines.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Defines.h @@ -1,4 +1,4 @@ -// Copyright(C) 2018 National Technology & Engineering Solutions +// Copyright(C) 2018, 2020 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -32,7 +32,10 @@ #ifndef IOSS_IOCGNS_DEFINES_H #define IOSS_IOCGNS_DEFINES_H +#include +#include #define CGNS_MAX_NAME_LENGTH 255 +using CGNSIntVector = std::vector; #endif diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C index f20780b44b05..4bae04422104 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C @@ -92,8 +92,8 @@ namespace { #endif } - void map_local_to_global_implicit(Iocgns::CGNSIntVector &data, ssize_t count, - const Iocgns::CGNSIntVector &global_implicit_map) + void map_local_to_global_implicit(CGNSIntVector &data, ssize_t count, + const CGNSIntVector &global_implicit_map) { for (ssize_t i = 0; i < count; i++) { data[i] = global_implicit_map[data[i] - 1]; @@ -449,14 +449,14 @@ namespace Iocgns { int id = 0; for (auto &sset : decomp->m_sideSets) { // See if there is an Ioss::SideSet with a matching name... - Ioss::SideSet *ioss_sset = get_region()->get_sideset(sset.name()); + Ioss::SideSet *ioss_sset = get_region()->get_sideset(sset.ss_name()); if (ioss_sset != nullptr) { auto zone = decomp->m_zones[sset.zone()]; std::string block_name = fmt::format("{}/{}", zone.m_name, sset.name()); std::string face_topo = sset.topologyType; #if IOSS_DEBUG_OUTPUT - fmt::print(stderr, "Processor {}: Added sideblock {} of topo {} with {} faces\n", - myProcessor, block_name, face_topo, sset.ioss_count()); + fmt::print(stderr, "Processor {}: Added sideblock '{}' of topo {} with {} faces to sset '{}'\n", + myProcessor, block_name, face_topo, sset.ioss_count(), ioss_sset->name()); #endif const auto &block = decomp->m_elementBlocks[sset.parentBlockIndex]; @@ -874,8 +874,8 @@ namespace Iocgns { common.resize(size); MPI_Bcast(common.data(), 2 * size, MPI_INT, 0, util().communicator()); - std::vector point_list; - std::vector point_list_donor; + CGNSIntVector point_list; + CGNSIntVector point_list_donor; point_list.reserve(common.size()); point_list_donor.reserve(common.size()); @@ -2339,9 +2339,6 @@ namespace Iocgns { // Handle the MESH fields required for a CGNS file model. // (The 'genesis' portion) if (field.get_name() == "element_side") { - // Get name from parent sideset... - auto &name = sb->owner()->name(); - CG_ElementType_t type = Utils::map_topology_to_cgns(sb->topology()->name()); int sect = 0; @@ -2356,7 +2353,12 @@ namespace Iocgns { // the data so would have to generate it. This may cause problems // with codes that use the downstream data if they base the BC off // of the nodes instead of the element/side info. - std::vector point_range{cg_start, cg_end}; + // Get name from parent sideset... This is name of the ZoneBC entry + auto &name = sb->owner()->name(); + // This is the name of the BC_t node + auto sb_name = Iocgns::Utils::decompose_sb_name(sb->name()); + + CGNSIntVector point_range{cg_start, cg_end}; CGCHECKM(cg_boco_write(get_file_pointer(), base, zone, name.c_str(), CG_FamilySpecified, CG_PointRange, 2, point_range.data(), §)); CGCHECKM( @@ -2364,7 +2366,7 @@ namespace Iocgns { CGCHECKM(cg_famname_write(name.c_str())); CGCHECKM(cg_boco_gridlocation_write(get_file_pointer(), base, zone, sect, CG_FaceCenter)); - CGCHECKM(cgp_section_write(get_file_pointer(), base, zone, name.c_str(), type, cg_start, + CGCHECKM(cgp_section_write(get_file_pointer(), base, zone, sb_name.c_str(), type, cg_start, cg_end, 0, §)); sb->property_update("section", sect); diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.h index 5df0876fae48..f6cf7f9539b6 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2017 National Technology & Engineering Solutions +// Copyright(C) 1999-2017, 2020 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -47,6 +47,7 @@ #include // for string #include +#include #include @@ -71,8 +72,6 @@ namespace Ioss { namespace Iocgns { - using CGNSIntVector = std::vector; - class ParallelDatabaseIO : public Ioss::DatabaseIO { public: diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C index 884b9de61abf..832b6fbee47d 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C @@ -415,6 +415,19 @@ std::pair Iocgns::Utils::decompose_name(const std::string &nam return std::make_pair(zname, proc); } +std::string Iocgns::Utils::decompose_sb_name(const std::string &name) +{ + std::string zname{name}; + + // Name should/might be of the form `zonename/sb_name`. Extract + // the 'sb_name' and return that + auto tokens = Ioss::tokenize(zname, "/"); + if (tokens.size() >= 2) { + zname = tokens.back(); + } + return zname; +} + void Iocgns::Utils::cgns_error(int cgnsid, const char *file, const char *function, int lineno, int processor) { @@ -1048,7 +1061,7 @@ size_t Iocgns::Utils::common_write_meta_data(int file_ptr, const Ioss::Region &r if (is_parallel_io) { region.get_database()->progress("\t\tBoundary Conditions"); } - std::vector bc_range(sb->m_boundaryConditions.size() * 6); + CGNSIntVector bc_range(sb->m_boundaryConditions.size() * 6); size_t idx = 0; for (const auto &bc : sb->m_boundaryConditions) { for (size_t i = 0; i < 3; i++) { @@ -2580,6 +2593,43 @@ size_t Iocgns::Utils::pre_split(std::vector &zones return new_zone_id; } +std::vector Iocgns::Utils::parse_zonebc_sideblocks(int cgns_file_ptr, int base, int zone, + int myProcessor) + { + int num_bc; + CGCHECK(cg_nbocos(cgns_file_ptr, base, zone, &num_bc)); + + std::vector zonebc; + zonebc.reserve(num_bc); + + for (int i = 0; i < num_bc; i++) { + char boco_name[CGNS_MAX_NAME_LENGTH + 1]; + CG_BCType_t boco_type; + CG_PointSetType_t ptset_type; + cgsize_t num_pnts; + cgsize_t normal_list_size; // ignore + CG_DataType_t normal_data_type; // ignore + int num_dataset; // ignore + CGCHECK(cg_boco_info(cgns_file_ptr, base, zone, i + 1, boco_name, &boco_type, &ptset_type, + &num_pnts, nullptr, &normal_list_size, &normal_data_type, &num_dataset)); + + if (num_pnts != 2 || ptset_type != CG_PointRange) { + std::ostringstream errmsg; + fmt::print( + errmsg, + "CGNS: In Zone {}, boundary condition '{}' has a PointSetType of '{}' and {} points.\n" + " The type must be 'PointRange' and there must be 2 points.", + zone, boco_name, cg_PointSetTypeName(ptset_type), num_pnts); + IOSS_ERROR(errmsg); + } + + std::array point_range; + CGCHECK(cg_boco_read(cgns_file_ptr, base, zone, i + 1, point_range.data(), nullptr)); + zonebc.emplace_back(boco_name, point_range); + } + return zonebc; + } + #ifdef CG_BUILD_HDF5 extern "C" int H5get_libversion(unsigned *, unsigned *, unsigned *); #endif diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h index 2c0473187fb6..658b06ee9740 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,18 @@ namespace Iocgns { class StructuredZoneData; + struct ZoneBC + { + ZoneBC(const std::string &bc_name, std::array &point_range) + : name(bc_name), range_beg(point_range[0]), range_end(point_range[1]) + { + } + + std::string name; + cgsize_t range_beg; + cgsize_t range_end; + }; + class Utils { public: @@ -83,6 +96,7 @@ namespace Iocgns { static const size_t CG_VERTEX_FIELD_ID = 1ul << 34; static std::pair decompose_name(const std::string &name, bool is_parallel); + static std::string decompose_sb_name(const std::string &name); static size_t index(const Ioss::Field &field); @@ -213,7 +227,7 @@ namespace Iocgns { } static void map_ioss_face_to_cgns(const Ioss::ElementTopology *parent_topo, size_t num_to_get, - std::vector &data) + CGNSIntVector &data) { // The {topo}_map[] arrays map from CGNS face# to IOSS face#. // See http://cgns.github.io/CGNS_docs_current/sids/conv.html#unstructgrid @@ -254,6 +268,9 @@ namespace Iocgns { } } + static std::vector parse_zonebc_sideblocks(int cgns_file_ptr, int base, int zone, + int myProcessor); + static void generate_boundary_faces(Ioss::Region * region, std::map &boundary_faces,