Skip to content

Commit

Permalink
Merge pull request #390 from sandialabs/add_ejoin_assemblies
Browse files Browse the repository at this point in the history
Add ejoin assemblies
  • Loading branch information
gsjaardema authored May 26, 2023
2 parents da2e11c + f5471d1 commit 7db697b
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 28 deletions.
38 changes: 32 additions & 6 deletions packages/seacas/applications/ejoin/EJ_SystemInterface.C
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void SystemInterface::enroll_options()
options_.enroll("version", GetLongOption::NoValue, "Print version and exit", nullptr);

options_.enroll("output", GetLongOption::MandatoryValue, "Name of output file to create",
"ejoin-out.e");
"ejoin-out.e", nullptr, true);

options_.enroll(
"extract_blocks", GetLongOption::MandatoryValue,
Expand All @@ -75,6 +75,19 @@ void SystemInterface::enroll_options()
"\t\t\t '-omit_blocks p1:1:3:4,p2:2:3:4,p5:8'",
nullptr);

options_.enroll("omit_assemblies", GetLongOption::MandatoryValue,
"If no value, then don't transfer any assemblies to output file.\n"
"\t\tIf just p#,p#,... specified, then omit assemblies on specified parts\n"
"\t\tIf p#:id1:id2,p#:id2,id4... then omit the assemblies with the specified\n"
"\t\tid in the specified parts.",
nullptr, "ALL");

options_.enroll(
"omit_part_assemblies", GetLongOption::NoValue,
"Do not create an assembly for each input part containing the blocks in that part.\n"
"\t\tDefault is to create the part assemblies.",
nullptr);

options_.enroll("omit_nodesets", GetLongOption::OptionalValue,
"If no value, then don't transfer any nodesets to output file.\n"
"\t\tIf just p#,p#,... specified, then omit sets on specified parts\n"
Expand All @@ -94,7 +107,7 @@ void SystemInterface::enroll_options()
"\t\tcreate a nodeset containing the nodes of that part\n"
"\t\tand output the nodal fields as nodeset fields instead of nodal fields.\n"
"\t\tFormat is comma-separated list of parts (1-based), or ALL",
nullptr);
nullptr, nullptr, true);

options_.enroll("match_node_ids", GetLongOption::NoValue,
"Combine nodes if their global ids match.", nullptr);
Expand All @@ -115,19 +128,20 @@ void SystemInterface::enroll_options()
#endif

options_.enroll("tolerance", GetLongOption::MandatoryValue,
"Maximum distance between two nodes to be considered colocated.", nullptr);
"Maximum distance between two nodes to be considered colocated.", nullptr,
nullptr, true);

options_.enroll(
"block_prefix", GetLongOption::MandatoryValue,
"Prefix used on the input block names of second and subsequent meshes to make them\n"
"\t\tunique. Default is 'p'. Example: block1, p1_block1, p2_block1.",
"\t\tunique. Default is 'p'. Example: block1, p2_block1, p3_block1.",
"p");

options_.enroll("offset", GetLongOption::MandatoryValue,
"Comma-separated x,y,z offset for coordinates of second and subsequent meshes.\n"
"\t\tThe offset will be multiplied by the part number-1 so:\n"
"\t\tP1: no offset; P2: 1x, 1y, 1z; P3: 2x, 2y, 2z; P(n+1): nx, ny, nz",
nullptr);
nullptr, nullptr, true);

options_.enroll("steps", GetLongOption::MandatoryValue,
"Specify subset of timesteps to transfer to output file.\n"
Expand Down Expand Up @@ -171,7 +185,7 @@ void SystemInterface::enroll_options()
"Ignore the element id maps on the input database and just use a 1..#elements id "
"map on output.\n"
"\t\tMuch faster for large models if do not need specific element global ids",
nullptr);
nullptr, nullptr, true);

options_.enroll("netcdf4", GetLongOption::NoValue,
"Create output database using the HDF5-based "
Expand Down Expand Up @@ -249,6 +263,7 @@ bool SystemInterface::parse_options(int argc, char **argv)
blockInclusions_.resize(part_count);
nsetOmissions_.resize(part_count);
ssetOmissions_.resize(part_count);
assemblyOmissions_.resize(part_count);

// Get options from environment variable also...
char *options = getenv("EJOIN_OPTIONS");
Expand Down Expand Up @@ -303,6 +318,17 @@ bool SystemInterface::parse_options(int argc, char **argv)
}
}

{
const char *temp = options_.retrieve("omit_assemblies");
if (temp != nullptr) {
parse_omissions(temp, &assemblyOmissions_, "assembly", true);
}
}

if (options_.retrieve("omit_part_assemblies") != nullptr) {
createAssemblies_ = false;
}

{
const char *temp = options_.retrieve("extract_blocks");
if (temp != nullptr) {
Expand Down
15 changes: 10 additions & 5 deletions packages/seacas/applications/ejoin/EJ_SystemInterface.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright(C) 1999-2022 National Technology & Engineering Solutions
// Copyright(C) 1999-, 20232023 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.
//
Expand Down Expand Up @@ -29,10 +29,12 @@ class SystemInterface
bool omit_nodesets() const { return omitNodesets_; }
bool omit_sidesets() const { return omitSidesets_; }
bool convert_nodes_to_nodesets(int part_number) const;
bool disable_field_recognition() const { return disableFieldRecognition_; }
bool ints64bit() const { return ints64bit_; }
bool use_netcdf4() const { return useNetcdf4_; }
bool ignore_element_ids() const { return ignoreElementIds_; }
bool create_assemblies() const { return createAssemblies_; }

bool disable_field_recognition() const { return disableFieldRecognition_; }
bool ints64bit() const { return ints64bit_; }
bool use_netcdf4() const { return useNetcdf4_; }
bool ignore_element_ids() const { return ignoreElementIds_; }

int compression_level() const { return compressionLevel_; }
bool zlib() const { return zlib_; }
Expand All @@ -53,6 +55,7 @@ class SystemInterface
const Omissions &block_omissions() const { return blockOmissions_; }
const Omissions &nset_omissions() const { return nsetOmissions_; }
const Omissions &sset_omissions() const { return ssetOmissions_; }
const Omissions &assembly_omissions() const { return assemblyOmissions_; }

const std::string &block_prefix() const { return blockPrefix_; }

Expand Down Expand Up @@ -96,6 +99,7 @@ class SystemInterface
bool ignoreElementIds_{false};
bool zlib_{true};
bool szip_{false};
bool createAssemblies_{true};

std::string blockPrefix_{"p"};

Expand All @@ -104,6 +108,7 @@ class SystemInterface

Omissions blockInclusions_;
Omissions blockOmissions_;
Omissions assemblyOmissions_;
Omissions nsetOmissions_;
Omissions ssetOmissions_;

Expand Down
4 changes: 2 additions & 2 deletions packages/seacas/applications/ejoin/EJ_Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@

static std::array<std::string, 3> qainfo{
"ejoin",
"2022/01/24",
"1.5.7",
"2023/05/26",
"1.6.0",
};
96 changes: 93 additions & 3 deletions packages/seacas/applications/ejoin/EJoin.C
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ namespace {
const std::vector<INT> &local_node_map, SystemInterface &interFace);
void process_nset_omissions(RegionVector &part_mesh, const Omissions &omit);
void process_sset_omissions(RegionVector &part_mesh, const Omissions &omit);
void process_assembly_omissions(RegionVector &part_mesh, const Omissions &omit);

int count_omissions(Ioss::Region *region)
{
Expand Down Expand Up @@ -123,7 +124,9 @@ namespace {
} // namespace

namespace {
void transfer_elementblock(Ioss::Region &region, Ioss::Region &output_region, bool debug);
void transfer_elementblock(Ioss::Region &region, Ioss::Region &output_region,
bool create_assemblies, bool debug);
void transfer_assembly(Ioss::Region &region, Ioss::Region &output_region, bool debug);
void transfer_nodesets(Ioss::Region &region, Ioss::Region &output_region, bool debug);
void transfer_sidesets(Ioss::Region &region, Ioss::Region &output_region, bool debug);
void create_nodal_nodeset(Ioss::Region &region, Ioss::Region &output_region, bool debug);
Expand Down Expand Up @@ -240,6 +243,7 @@ int main(int argc, char *argv[])

process_nset_omissions(part_mesh, interFace.nset_omissions());
process_sset_omissions(part_mesh, interFace.sset_omissions());
process_assembly_omissions(part_mesh, interFace.assembly_omissions());

double time = 0.0;

Expand Down Expand Up @@ -404,7 +408,7 @@ double ejoin(SystemInterface &interFace, std::vector<Ioss::Region *> &part_mesh,

// Add element blocks, nodesets, sidesets
for (size_t p = 0; p < part_count; p++) {
transfer_elementblock(*part_mesh[p], output_region, false);
transfer_elementblock(*part_mesh[p], output_region, interFace.create_assemblies(), false);
if (interFace.convert_nodes_to_nodesets(p + 1)) {
create_nodal_nodeset(*part_mesh[p], output_region, false);
}
Expand All @@ -414,6 +418,7 @@ double ejoin(SystemInterface &interFace, std::vector<Ioss::Region *> &part_mesh,
if (!interFace.omit_sidesets()) {
transfer_sidesets(*part_mesh[p], output_region, false);
}
transfer_assembly(*part_mesh[p], output_region, false);
}

if (!interFace.information_record_parts().empty()) {
Expand Down Expand Up @@ -565,11 +570,19 @@ namespace {
return omitted;
}

void transfer_elementblock(Ioss::Region &region, Ioss::Region &output_region, bool debug)
void transfer_elementblock(Ioss::Region &region, Ioss::Region &output_region,
bool create_assemblies, bool debug)
{
static int used_blocks = 0;
const std::string &prefix = region.name();

Ioss::Assembly *assem = nullptr;
if (create_assemblies) {
assem = new Ioss::Assembly(output_region.get_database(), region.name());
output_region.add(assem);
assem->property_add(Ioss::Property("name_in_output", region.name()));
}

const Ioss::ElementBlockContainer &ebs = region.get_element_blocks();
for (const auto &eb : ebs) {
if (!entity_is_omitted(eb)) {
Expand All @@ -581,6 +594,8 @@ namespace {
exit(EXIT_FAILURE);
}
}
eb->property_add(Ioss::Property("name_in_output", name));

if (debug) {
fmt::print(stderr, "{}, ", name);
}
Expand All @@ -601,6 +616,54 @@ namespace {
// Set the new property
ebn->property_add(Ioss::Property("original_topology_type", oes));
}

if (create_assemblies) {
assem->add(ebn);
}
}
}
}
}

void transfer_assembly(Ioss::Region &region, Ioss::Region &output_region, bool debug)
{
// All assemblies on the input parts will be transferred to the output mesh
// Possibly renamed if a name conflict
// Also need to update names of the entities in the assembly since they were possibly
// renamed on the output...
// TODO: handle renamed nested assemblies...
const std::string &prefix = region.name();

const Ioss::AssemblyContainer &assems = region.get_assemblies();
for (const auto &as : assems) {
if (!entity_is_omitted(as)) {
std::string name = as->name();
if (output_region.get_assembly(name) != nullptr) {
name = prefix + "_" + as->name();
if (output_region.get_assembly(name) != nullptr) {
fmt::print(stderr, "ERROR: Duplicate assemblies named '{}'\n", name);
exit(EXIT_FAILURE);
}
}
as->property_add(Ioss::Property("name_in_output", name));

if (debug) {
fmt::print(stderr, "{}, ", name);
}
size_t num_members = as->entity_count();
if (num_members > 0) {
auto member_type = as->get_member_type();
auto asn = new Ioss::Assembly(output_region.get_database(), name);
output_region.add(asn);

const auto &members = as->get_members();
for (const auto &member : members) {
auto output_name = member->get_property("name_in_output").get_string();

auto *entity = output_region.get_entity(output_name, member_type);
assert(entity != nullptr);
asn->add(entity);
}
}
}
}
Expand All @@ -621,6 +684,7 @@ namespace {
exit(EXIT_FAILURE);
}
}
fs->property_add(Ioss::Property("name_in_output", name));
if (debug) {
fmt::print(stderr, "{}, ", name);
}
Expand All @@ -633,6 +697,7 @@ namespace {
if (debug) {
fmt::print(stderr, "{}, ", fbname);
}
fb->property_add(Ioss::Property("name_in_output", fbname));
std::string fbtype = fb->topology()->name();
std::string partype = fb->parent_element_topology()->name();
size_t num_side = fb->entity_count();
Expand Down Expand Up @@ -747,6 +812,7 @@ namespace {
exit(EXIT_FAILURE);
}
}
ns->property_add(Ioss::Property("name_in_output", name));
if (debug) {
fmt::print(stderr, "{}, ", name);
}
Expand Down Expand Up @@ -1493,4 +1559,28 @@ namespace {
}
}
}

void process_assembly_omissions(RegionVector &part_mesh, const Omissions &omit)
{
size_t part_count = part_mesh.size();
for (size_t p = 0; p < part_count; p++) {
if (!omit[p].empty()) {
// Get the assemblies for this part and set the "omitted" property on the assembly
if (omit[p][0] == "ALL") {
const auto &assemblies = part_mesh[p]->get_assemblies();
for (auto &as : assemblies) {
as->property_add(Ioss::Property(std::string("omitted"), 1));
}
}
else {
for (const auto &omitted : omit[p]) {
auto *as = part_mesh[p]->get_assembly(omitted);
if (as != nullptr) {
as->property_add(Ioss::Property(std::string("omitted"), 1));
}
}
}
}
}
}
} // namespace
6 changes: 3 additions & 3 deletions packages/seacas/libraries/exodus/include/exodusII.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@
#endif

/* EXODUS version number */
#define EXODUS_VERSION "8.20"
#define EXODUS_VERSION "8.21"
#define EXODUS_VERSION_MAJOR 8
#define EXODUS_VERSION_MINOR 20
#define EXODUS_VERSION_MINOR 21
#define EXODUS_RELEASE_DATE "May 1, 2023"

#define EX_API_VERS 8.20f
#define EX_API_VERS 8.21f
#define EX_API_VERS_NODOT (100 * EXODUS_VERSION_MAJOR + EXODUS_VERSION_MINOR)
#define EX_VERS EX_API_VERS

Expand Down
Loading

0 comments on commit 7db697b

Please sign in to comment.