Skip to content

Commit

Permalink
Merge pull request #430 from tokusanya/TextMeshOmitBlocks
Browse files Browse the repository at this point in the history
TextMesh: Enable block and assembly omission/inclusion
  • Loading branch information
gsjaardema authored Jan 18, 2024
2 parents d946b06 + f274843 commit b5964b0
Show file tree
Hide file tree
Showing 9 changed files with 414 additions and 22 deletions.
46 changes: 46 additions & 0 deletions packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,34 @@ namespace Ioss {
void DatabaseIO::set_block_omissions(const std::vector<std::string> &omissions,
const std::vector<std::string> &inclusions)
{
if (!omissions.empty() && !inclusions.empty()) {
// Only one can be non-empty
std::ostringstream errmsg;
fmt::print(errmsg,
"ERROR: Only one of element block omission or inclusion can be non-empty"
" [{}]\n",
get_filename());
IOSS_ERROR(errmsg);
}

if (!assemblyOmissions.empty() && !inclusions.empty()) {
std::ostringstream errmsg;
fmt::print(errmsg,
"ERROR: Only one of element block inclusion or assembly omission can be non-empty"
" [{}]\n",
get_filename());
IOSS_ERROR(errmsg);
}

if (!assemblyInclusions.empty() && !omissions.empty()) {
std::ostringstream errmsg;
fmt::print(errmsg,
"ERROR: Only one of element block omission or assembly inclusion can be non-empty"
" [{}]\n",
get_filename());
IOSS_ERROR(errmsg);
}

if (!omissions.empty()) {
blockOmissions.assign(omissions.cbegin(), omissions.cend());
Ioss::sort(blockOmissions.begin(), blockOmissions.end());
Expand All @@ -900,6 +928,24 @@ namespace Ioss {
IOSS_ERROR(errmsg);
}

if (!blockOmissions.empty() && !inclusions.empty()) {
std::ostringstream errmsg;
fmt::print(errmsg,
"ERROR: Only one of element block omission or assembly inclusion can be non-empty"
" [{}]\n",
get_filename());
IOSS_ERROR(errmsg);
}

if (!blockInclusions.empty() && !omissions.empty()) {
std::ostringstream errmsg;
fmt::print(errmsg,
"ERROR: Only one of element block inclusion or assembly omission can be non-empty"
" [{}]\n",
get_filename());
IOSS_ERROR(errmsg);
}

if (!omissions.empty()) {
assemblyOmissions.assign(omissions.cbegin(), omissions.cend());
Ioss::sort(assemblyOmissions.begin(), assemblyOmissions.end());
Expand Down
8 changes: 8 additions & 0 deletions packages/seacas/libraries/ioss/src/Ioss_Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,14 @@ namespace Ioss {
const std::string &header, const std::string &suffix = "\n\t",
bool print_empty = false);

static void insert_sort_and_unique(const std::vector<std::string> &src, std::vector<std::string> &dest)
{
dest.insert(dest.end(), src.begin(), src.end());
std::sort(dest.begin(), dest.end(), std::less<>());
auto endIter = std::unique(dest.begin(), dest.end());
dest.resize(endIter - dest.begin());
}

private:
// SEE: http://lemire.me/blog/2017/04/10/removing-duplicates-from-lists-quickly
template <typename T> static size_t unique(std::vector<T> &out, bool skip_first)
Expand Down
22 changes: 2 additions & 20 deletions packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ namespace {
template <typename T>
void write_attribute_names(int exoid, ex_entity_type type, const std::vector<T *> &entities);

void insert_sort_and_unique(const std::vector<std::string> &src, std::vector<std::string> &dest);

class AssemblyTreeFilter
{
public:
Expand Down Expand Up @@ -691,14 +689,6 @@ namespace Ioex {
{
Ioss::SerializeIO serializeIO_(this);

if (!assemblyOmissions.empty()) {
assert(blockInclusions.empty());
}

if (!assemblyInclusions.empty()) {
assert(blockOmissions.empty());
}

// Query number of assemblies...
auto assemblies = get_exodus_assemblies(get_file_pointer());
if (!assemblies.empty()) {
Expand Down Expand Up @@ -730,8 +720,8 @@ namespace Ioex {

cleanup_exodus_assembly_vector(assemblies);

insert_sort_and_unique(exclusions, blockOmissions);
insert_sort_and_unique(inclusions, blockInclusions);
Ioss::Utils::insert_sort_and_unique(exclusions, blockOmissions);
Ioss::Utils::insert_sort_and_unique(inclusions, blockInclusions);
}
}

Expand Down Expand Up @@ -3129,12 +3119,4 @@ namespace {
}
#endif
}

void insert_sort_and_unique(const std::vector<std::string> &src, std::vector<std::string> &dest)
{
dest.insert(dest.end(), src.begin(), src.end());
std::sort(dest.begin(), dest.end(), std::less<>());
auto endIter = std::unique(dest.begin(), dest.end());
dest.resize(endIter - dest.begin());
}
} // namespace
38 changes: 38 additions & 0 deletions packages/seacas/libraries/ioss/src/text_mesh/Iotm_DatabaseIO.C
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,13 @@ namespace Iotm {
}
}

void DatabaseIO::update_block_omissions_from_assemblies()
{
m_textMesh->update_block_omissions_from_assemblies(get_region(),
assemblyOmissions, assemblyInclusions,
blockOmissions, blockInclusions);
}

void DatabaseIO::get_elemblocks()
{
// Attributes of an element block are:
Expand Down Expand Up @@ -675,6 +682,37 @@ namespace Iotm {

order++;
}

if (!assemblyOmissions.empty() || !assemblyInclusions.empty()) {
update_block_omissions_from_assemblies();
}

assert(blockOmissions.empty() || blockInclusions.empty()); // Only one can be non-empty

// Handle all block omissions or inclusions...
if (!blockOmissions.empty()) {
for (const auto &name : blockOmissions) {
auto block = get_region()->get_element_block(name);
if (block != nullptr) {
block->property_add(Ioss::Property(std::string("omitted"), 1));
}
}
}

if (!blockInclusions.empty()) {
const auto &blocks = get_region()->get_element_blocks();
for (auto &block : blocks) {
block->property_add(Ioss::Property(std::string("omitted"), 1));
}

// Now, erase the property on any blocks in the inclusion list...
for (const auto &name : blockInclusions) {
auto block = get_region()->get_element_block(name);
if (block != nullptr) {
block->property_erase("omitted");
}
}
}
}

void DatabaseIO::get_nodesets()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ namespace Iotm {
void get_commsets();
void get_assemblies();

void update_block_omissions_from_assemblies();

const Ioss::Map &get_node_map() const;
const Ioss::Map &get_element_map() const;

Expand Down
115 changes: 114 additions & 1 deletion packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,79 @@
} while (false)

namespace Iotm {

class AssemblyTreeFilter
{
public:
AssemblyTreeFilter() = delete;
AssemblyTreeFilter(const AssemblyTreeFilter &) = delete;

AssemblyTreeFilter(Ioss::Region *region, const Ioss::EntityType filterType, const Assemblies &assemblies)
: m_region(region),
m_type(filterType),
m_assemblies(assemblies)
{
for (const std::string& assemblyName : m_assemblies.get_part_names()) {
m_visitedAssemblies[assemblyName] = false;
}
}

void update_list_from_assembly_tree(const AssemblyData *assembly, std::vector<std::string> &list)
{
// Walk the tree without cyclic dependency
if (nullptr != assembly) {
if (!m_visitedAssemblies[assembly->name]) {
m_visitedAssemblies[assembly->name] = true;

const Ioss::EntityType assemblyType = TextMesh::assembly_type_to_entity_type(assembly->get_assembly_type());
if (m_type == assemblyType) {
for (const std::string& assemblyMember : assembly->data) {
Ioss::GroupingEntity *ge = m_region->get_entity(assemblyMember, m_type);
if (nullptr != ge) {
list.push_back(ge->name());
}
}
}

if (Ioss::ASSEMBLY == assemblyType) {
for (const std::string& subAssemblyName : assembly->data) {
// Find the sub assembly
const AssemblyData *subAssembly = m_assemblies.get_group_data(subAssemblyName);

if (nullptr != subAssembly) {
update_list_from_assembly_tree(subAssembly, list);
} else {
std::ostringstream errmsg;
fmt::print(errmsg, "ERROR: Could not find sub-assembly with id: {} and name: {}",
assembly->id, assembly->name);
IOSS_ERROR(errmsg);
}
}
}
}
}
}

void update_assembly_filter_list(std::vector<std::string> &assemblyFilterList)
{
for (const std::string& assemblyName : m_assemblies.get_part_names()) {
if (m_visitedAssemblies[assemblyName]) {
assemblyFilterList.emplace_back(assemblyName);
}
}

std::sort(assemblyFilterList.begin(), assemblyFilterList.end(), std::less<>());
auto endIter = std::unique(assemblyFilterList.begin(), assemblyFilterList.end());
assemblyFilterList.resize(endIter - assemblyFilterList.begin());
}

private:
Ioss::Region *m_region = nullptr;
Ioss::EntityType m_type = Ioss::INVALID_TYPE;
const Assemblies &m_assemblies;
mutable std::map<std::string,bool> m_visitedAssemblies;
};

void error_handler(const std::ostringstream &message) { throw std::logic_error((message).str()); }

TextMesh::TextMesh(int, int my_proc) : m_myProcessor(my_proc)
Expand Down Expand Up @@ -634,7 +707,7 @@ namespace Iotm {
return assembly->id;
}

Ioss::EntityType TextMesh::assembly_type_to_entity_type(const AssemblyType type) const
Ioss::EntityType TextMesh::assembly_type_to_entity_type(const AssemblyType type)
{
if (type == AssemblyType::BLOCK) {
return Ioss::ELEMENTBLOCK;
Expand Down Expand Up @@ -844,4 +917,44 @@ namespace Iotm {

return sideset->get_split_type();
}

void TextMesh::update_block_omissions_from_assemblies(Ioss::Region *region,
std::vector<std::string>& assemblyOmissions,
std::vector<std::string>& assemblyInclusions,
std::vector<std::string>& blockOmissions,
std::vector<std::string>& blockInclusions) const
{
// Query number of assemblies...
if (assembly_count() > 0) {
std::vector<std::string> exclusions;
std::vector<std::string> inclusions;

AssemblyTreeFilter inclusionFilter(region, Ioss::ELEMENTBLOCK, m_data.assemblies);
AssemblyTreeFilter exclusionFilter(region, Ioss::ELEMENTBLOCK, m_data.assemblies);

for (const std::string& assemblyName : m_data.assemblies.get_part_names()) {
const AssemblyData *assembly = m_data.assemblies.get_group_data(assemblyName);

bool omitAssembly =
std::binary_search(assemblyOmissions.begin(), assemblyOmissions.end(), assembly->name);
bool includeAssembly =
std::binary_search(assemblyInclusions.begin(), assemblyInclusions.end(), assembly->name);

if (omitAssembly) {
exclusionFilter.update_list_from_assembly_tree(assembly, exclusions);
}

if (includeAssembly) {
inclusionFilter.update_list_from_assembly_tree(assembly, inclusions);
}
}

exclusionFilter.update_assembly_filter_list(assemblyOmissions);
inclusionFilter.update_assembly_filter_list(assemblyInclusions);

Ioss::Utils::insert_sort_and_unique(exclusions, blockOmissions);
Ioss::Utils::insert_sort_and_unique(inclusions, blockInclusions);
}
}

} // namespace Iotm
10 changes: 9 additions & 1 deletion packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "Ioss_CodeTypes.h"
#include "Ioss_EntityType.h" // for EntityType
#include "Ioss_Region.h"
#include <cstddef> // for size_t
#include <cstdint> // for int64_t
#include <map> // for map, etc
Expand All @@ -34,6 +35,7 @@ namespace Iotm {
using ElementData = text_mesh::ElementData<int64_t, Topology>;
using SidesetData = text_mesh::SidesetData<int64_t, Topology>;
using NodesetData = text_mesh::NodesetData<int64_t>;
using Assemblies = text_mesh::Assemblies<int64_t>;
using AssemblyData = text_mesh::AssemblyData;
using Coordinates = text_mesh::Coordinates<int64_t>;
using TextMeshParser = text_mesh::TextMeshParser<int64_t, IossTopologyMapping>;
Expand Down Expand Up @@ -283,7 +285,13 @@ namespace Iotm {
Ioss::EntityType get_assembly_type(const std::string &name) const;
std::vector<std::string> get_assembly_members(const std::string &name) const;

Ioss::EntityType assembly_type_to_entity_type(const AssemblyType type) const;
static Ioss::EntityType assembly_type_to_entity_type(const AssemblyType type);

void update_block_omissions_from_assemblies(Ioss::Region *region,
std::vector<std::string>& assemblyOmissions,
std::vector<std::string>& assemblyInclusions,
std::vector<std::string>& blockOmissions,
std::vector<std::string>& blockInclusions) const;

unsigned spatial_dimension() const;

Expand Down
17 changes: 17 additions & 0 deletions packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ TRIBITS_ADD_EXECUTABLE(
SOURCES unitMain.C UnitTestTextMesh.C
)

TRIBITS_ADD_EXECUTABLE(
Utst_iotm
SOURCES unitMain.C UnitTestIotmDatabaseIO.C
)

TRIBITS_ADD_EXECUTABLE(
Utst_blockbatchread
SOURCES unitMain.C UnitTestElementBlockBatchRead.C
Expand Down Expand Up @@ -51,6 +56,18 @@ TRIBITS_ADD_TEST(
NUM_MPI_PROCS 4
)

TRIBITS_ADD_TEST(
Utst_iotm
NAME Utst_iotm
NUM_MPI_PROCS 1
)

TRIBITS_ADD_TEST(
Utst_iotm
NAME Utst_iotm
NUM_MPI_PROCS 2
)

TRIBITS_INCLUDE_DIRECTORIES(
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/../"
Expand Down
Loading

0 comments on commit b5964b0

Please sign in to comment.