From 95000d55f37a227274d234173392477efddb060e Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 17 Jul 2024 20:59:56 -0600 Subject: [PATCH] Revert "Dynamic topology region file opening with group I/O (#469)" This reverts commit ace7af0168c7d9a8649ffb3e7c587c69700ace27. --- .../libraries/ioss/src/Ioss_DatabaseIO.C | 5 - .../libraries/ioss/src/Ioss_DatabaseIO.h | 31 +- .../libraries/ioss/src/Ioss_DynamicTopology.C | 554 -------------- .../libraries/ioss/src/Ioss_DynamicTopology.h | 144 ---- .../libraries/ioss/src/Ioss_IOFactory.C | 2 - .../seacas/libraries/ioss/src/Ioss_Region.C | 323 ++------- .../seacas/libraries/ioss/src/Ioss_Region.h | 35 - .../ioss/src/exodus/Ioex_BaseDatabaseIO.C | 109 --- .../ioss/src/exodus/Ioex_BaseDatabaseIO.h | 4 - .../libraries/ioss/src/exodus/Ioex_Utils.C | 3 +- .../ioss/src/unit_tests/CMakeLists.txt | 11 - .../src/unit_tests/UnitTestDynamicTopology.C | 679 ------------------ 12 files changed, 55 insertions(+), 1845 deletions(-) delete mode 100644 packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.C delete mode 100644 packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.h delete mode 100644 packages/seacas/libraries/ioss/src/unit_tests/UnitTestDynamicTopology.C diff --git a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C index 870140a1d2..bee5f80d1d 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C @@ -379,11 +379,6 @@ namespace Ioss { DatabaseIO::~DatabaseIO() = default; - Ioss::DataSize DatabaseIO::int_byte_size_data_size() const - { - return dbIntSizeAPI; - } - int DatabaseIO::int_byte_size_api() const { if (dbIntSizeAPI == USE_INT32_API) { diff --git a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h index 5d193ed64f..f5edcdb3b4 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h @@ -279,18 +279,6 @@ namespace Ioss { return create_subgroup_nl(group_name); } - bool open_root_group() - { - IOSS_FUNC_ENTER(m_); - return open_root_group_nl(); - } - - Ioss::NameList groups_describe(bool return_full_names = false) - { - IOSS_FUNC_ENTER(m_); - return groups_describe_nl(return_full_names); - } - /** \brief Set the database to the given State. * * All transitions must begin from the 'STATE_CLOSED' state or be to @@ -514,7 +502,6 @@ namespace Ioss { IOSS_NODISCARD virtual int int_byte_size_db() const = 0; //! Returns 4 or 8 IOSS_NODISCARD int int_byte_size_api() const; //! Returns 4 or 8 virtual void set_int_byte_size_api(Ioss::DataSize size) const; - IOSS_NODISCARD Ioss::DataSize int_byte_size_data_size() const; /*! * The owning region of this database. @@ -750,14 +737,6 @@ namespace Ioss { virtual void closeDatabase_nl() const; virtual void flush_database_nl() const {} - virtual void release_memory_nl() - { - nodeMap.release_memory(); - edgeMap.release_memory(); - faceMap.release_memory(); - elemMap.release_memory(); - } - private: virtual bool ok_nl(bool /* write_message */, std::string * /* error_message */, int *bad_count) const @@ -778,10 +757,16 @@ namespace Ioss { return elemMap.global_to_local(global); } - virtual bool open_root_group_nl() { return false; } + virtual void release_memory_nl() + { + nodeMap.release_memory(); + edgeMap.release_memory(); + faceMap.release_memory(); + elemMap.release_memory(); + } + virtual bool open_group_nl(const std::string & /* group_name */) { return false; } virtual bool create_subgroup_nl(const std::string & /* group_name */) { return false; } - virtual Ioss::NameList groups_describe_nl(bool /* return_full_names */) { return Ioss::NameList(); } virtual bool begin_nl(Ioss::State state) = 0; virtual bool end_nl(Ioss::State state) = 0; diff --git a/packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.C b/packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.C deleted file mode 100644 index ac5af4849e..0000000000 --- a/packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.C +++ /dev/null @@ -1,554 +0,0 @@ -// Copyright(C) 2024 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. -// -// See packages/seacas/LICENSE for details - -#include "Ioss_Assembly.h" -#include "Ioss_Blob.h" -#include "Ioss_CodeTypes.h" -#include "Ioss_CommSet.h" -#include "Ioss_DBUsage.h" -#include "Ioss_DatabaseIO.h" -#include "Ioss_DynamicTopology.h" -#include "Ioss_EdgeBlock.h" -#include "Ioss_EdgeSet.h" -#include "Ioss_ElementBlock.h" -#include "Ioss_ElementSet.h" -#include "Ioss_EntityBlock.h" -#include "Ioss_EntityType.h" -#include "Ioss_FaceBlock.h" -#include "Ioss_FaceSet.h" -#include "Ioss_Field.h" -#include "Ioss_FileInfo.h" -#include "Ioss_GroupingEntity.h" -#include "Ioss_IOFactory.h" -#include "Ioss_NodeBlock.h" -#include "Ioss_NodeSet.h" -#include "Ioss_Region.h" -#include "Ioss_SideBlock.h" -#include "Ioss_SideSet.h" -#include "Ioss_StructuredBlock.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Ioss_ParallelUtils.h" - -namespace Ioss { - -void DynamicTopologyObserver::check_region() const -{ - if(nullptr == m_region) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: A region has not been registered with the " - "Dynamic Topology Observer.\n\n"); - IOSS_ERROR(errmsg); - } -} - -void DynamicTopologyObserver::register_region(Region *region) -{ - if(nullptr != m_region && region != m_region) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: Attempt to re-register different region on " - "Dynamic Topology Observer.\n\n"); - IOSS_ERROR(errmsg); - } - - m_region = region; -} - -void DynamicTopologyObserver::set_cumulative_topology_modification(unsigned int type) -{ m_cumulativeTopologyModification = type; } - -unsigned int DynamicTopologyObserver::get_cumulative_topology_modification() const -{ return m_cumulativeTopologyModification; } - -unsigned int DynamicTopologyObserver::get_topology_modification() const -{ return m_topologyModification; } - -void DynamicTopologyObserver::set_topology_modification(unsigned int type) -{ - m_topologyModification |= type; - m_cumulativeTopologyModification |= type; -} - -void DynamicTopologyObserver::reset_topology_modification() -{ - m_topologyModification = TOPOLOGY_SAME; -} - -bool DynamicTopologyObserver::is_topology_modified() const -{ return m_topologyModification != 0; } - -const ParallelUtils &DynamicTopologyObserver::util() const -{ - check_region(); - return m_region->get_database()->util(); -} - -void DynamicTopologyObserver::synchronize_topology_modified_flags() -{ - check_region(); - int num_processors = m_region->get_database()->parallel_size(); - // Synchronize the topology flags between all processors in case - // it has not been set consistently. - if (num_processors > 1) { - static unsigned int buffer[2]; - buffer[0] = m_cumulativeTopologyModification; - buffer[1] = m_topologyModification; - - util().attribute_reduction(2*sizeof(unsigned int), reinterpret_cast(buffer)); - - m_cumulativeTopologyModification = buffer[0]; - m_topologyModification = buffer[1]; - } -} - -int DynamicTopologyObserver::get_cumulative_topology_modification_field() -{ - check_region(); - const std::string variable_name = topology_modification_change_name(); - - int ivalue = 0; - - if (m_region->field_exists(variable_name)) { - Field topo_field = m_region->get_field(variable_name); - if (topo_field.get_type() == Field::INTEGER) { - m_region->get_field_data(variable_name, &ivalue, sizeof(int)); - } else { - double value; - m_region->get_field_data(variable_name, &value, sizeof(double)); - ivalue = (int)value; - } - } - - int num_processors = m_region->get_database()->parallel_size(); - // Synchronize the value between all processors in case - // it has not been set consistently. - if (num_processors > 1) { - unsigned int buffer[1]; - buffer[0] = ivalue; - - util().attribute_reduction(sizeof(unsigned int), reinterpret_cast(buffer)); - - ivalue = (int)buffer[0]; - } - - m_cumulativeTopologyModification = ivalue; - - return ivalue; -} - -void DynamicTopologyObserver::define_model(IOSS_MAYBE_UNUSED Region& region) -{ - -} - -void DynamicTopologyObserver::write_model(IOSS_MAYBE_UNUSED Region& region) -{ - -} - -void DynamicTopologyObserver::define_transient(IOSS_MAYBE_UNUSED Region& region) -{ - -} - -DynamicTopologyFileControl::DynamicTopologyFileControl(Region *region, unsigned int fileCyclicCount, - IfDatabaseExistsBehavior &ifDatabaseExists, - unsigned int &dbChangeCount) - : m_region(region) - , m_fileCyclicCount(fileCyclicCount) - , m_ifDatabaseExists(ifDatabaseExists) - , m_dbChangeCount(dbChangeCount) -{ - if(nullptr == region) { - std::ostringstream errmsg; - fmt::print(errmsg, "ERROR: null region passed in as argument to DynamicTopologyFileControl"); - IOSS_ERROR(errmsg); - } - - m_ioDB = region->get_property("base_filename").get_string(); - m_dbType = region->get_property("database_type").get_string(); -} - -const ParallelUtils &DynamicTopologyFileControl::util() const -{ - return m_region->get_database()->util(); -} - -bool DynamicTopologyFileControl::file_exists(const std::string &filename, - const std::string &db_type, - Ioss::DatabaseUsage db_usage) -{ - bool exists = false; - int par_size = m_region->get_database()->parallel_size(); - int par_rank = m_region->get_database()->parallel_rank(); - bool is_parallel = par_size > 1; - std::string full_filename = filename; - if (is_parallel && db_type == "exodusII" && db_usage != Ioss::WRITE_HISTORY) { - full_filename = Ioss::Utils::decode_filename(filename, par_rank, par_size); - } - - if (!is_parallel || par_rank == 0) { - // Now, see if this file exists... - // Don't want to do a system call on all processors since it can take minutes - // on some of the larger machines, filesystems, and processor counts... - Ioss::FileInfo file = Ioss::FileInfo(full_filename); - exists = file.exists(); - } - - if (is_parallel) { - int iexists = exists ? 1 : 0; - util().broadcast(iexists, 0); - exists = iexists == 1; - } - return exists; -} - -std::string DynamicTopologyFileControl::get_unique_filename(Ioss::DatabaseUsage db_usage) -{ - std::string filename = m_ioDB; - - do { - // Run this loop at least once for all files. If this is an automatic - // restart, then make sure that the generated file does not already exist, - // so keep running the loop until we generate a filename that doesn't exist... - std::ostringstream tmp_filename; - tmp_filename << m_ioDB; - - // Don't append the "-s000X" the first time in case the base filename doesn't - // exist -- we want write to the name specified by the user if at all possible and - // once that exists, then start adding on the suffix... - if (m_dbChangeCount > 1) { - tmp_filename << "-s" << std::setw(4) << std::setfill('0') << m_dbChangeCount; - } - filename = tmp_filename.str(); - ++m_dbChangeCount; - } while(file_exists(filename, m_dbType, db_usage)); - --m_dbChangeCount; - return filename; -} - -std::string DynamicTopologyFileControl::construct_database_filename(int& step, Ioss::DatabaseUsage db_usage) -{ - // Filename will be of the form -- ioDB-sxxxx where xxxx is step - // number. Assume maximum of 9999 steps (will do more, but won't have - // good lineup of step numbers. - // Check database for validity (filename and a type) - if(m_ioDB.empty() || m_dbType.empty()) - { - std::string error_message; - if(m_dbType.empty()) - error_message += "The database TYPE has not been defined\n"; - - if(m_ioDB.empty()) - { - error_message += "The database FILENAME has not been defined\n"; - } - std::ostringstream errmsg; - fmt::print(errmsg, error_message); - IOSS_ERROR(errmsg); - } - assert(!m_ioDB.empty()); - assert(!m_dbType.empty()); - std::string filename = m_ioDB; - if(m_fileCyclicCount > 0) - { - // In this mode, we close the old file and open a new file - // every time this is called. The file suffix cycles through - // the first fileCyclicCount'th entries in A,B,C,D,E,F,... - if(step == 0) - step++; - - static std::string suffix = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - std::string tmp = "-" + suffix.substr((step - 1) % m_fileCyclicCount, 1); - filename += tmp; - m_properties.add(Ioss::Property("APPEND_OUTPUT", Ioss::DB_OVERWRITE)); - } - else - { - if(m_region->model_is_written()) - { - // After the initial open, we want to add suffix if the topology changes - // during the run - m_ifDatabaseExists = Ioss::DB_ADD_SUFFIX_OVERWRITE; - } - - // Handle complications of DB_APPEND mode... - // If in DB_APPEND mode, then we don't output metadata - // information, so some knowledge is needed at this level if - // we are appending. If user specified APPEND, but the file - // doesn't yet exist OR it does exist and we are not - // restarting, change the mode to OVERWRITE. - // 0. Must be restarting; either manual or automatic. - std::shared_ptr observer = m_region->get_mesh_modification_observer(); - - if(m_ifDatabaseExists == Ioss::DB_APPEND) - { - if(!observer->is_restart_requested()) - { - // Not restarting - m_ifDatabaseExists = Ioss::DB_OVERWRITE; - } - else if(!file_exists(m_ioDB, m_dbType, db_usage)) - { - m_ifDatabaseExists = Ioss::DB_OVERWRITE; - } - } - if(step > 1 || (m_dbChangeCount > 1)) - { - // Use the !is_input_event test since restart input files already have the - // -s000x extension... - if(m_ifDatabaseExists == Ioss::DB_APPEND) - { - std::ostringstream tmp_filename; - tmp_filename << m_ioDB; - filename = m_ioDB; - if(m_dbChangeCount > 1) - { - tmp_filename << "-s" << std::setw(4) << std::setfill('0') << m_dbChangeCount; - } - size_t inc = 0; - while(file_exists(tmp_filename.str(), m_dbType, db_usage)) - { - filename = tmp_filename.str(); - tmp_filename.clear(); - tmp_filename.str(""); - tmp_filename << m_ioDB << "-s" << std::setw(4) << std::setfill('0') << m_dbChangeCount + (++inc); - } - if(inc > 0) - { - m_dbChangeCount += (inc - 1); - } - else - { - m_ifDatabaseExists = Ioss::DB_OVERWRITE; - } - } - else if(m_ifDatabaseExists == Ioss::DB_ADD_SUFFIX) - { - filename = get_unique_filename(db_usage); - } - else if(m_ifDatabaseExists == Ioss::DB_ADD_SUFFIX_OVERWRITE) - { - if(m_dbChangeCount > 0) - { - std::ostringstream tmp_filename; - tmp_filename << m_ioDB << "-s" << std::setw(4) << std::setfill('0') << ++m_dbChangeCount; - filename = tmp_filename.str(); - } - else - { - filename = m_ioDB; - } - } - else - { - filename = m_ioDB; - } - } - else if(m_ifDatabaseExists == Ioss::DB_ADD_SUFFIX) - { - filename = get_unique_filename(db_usage); - } - else - { - filename = m_ioDB; - } - - m_properties.add(Ioss::Property("APPEND_OUTPUT", m_ifDatabaseExists)); - // A little complicated on deciding whether we are actually - // overwriting the database. The 'validate' routine for Results and - // History will call create_database once the parser block is - // ended. This routine will then create the database and the - // ioRegion_. However, the database will not really be opened or - // written to at this time. If the code is auto-restarting, then it will - // detect that the database exists and create a database with the - // -s000x extension. - // At this point, we need to skip the 'abort_if_exists' test if we - // are in this routine from the 'validate' and we are restarting - // since we won't really write to the file. So, the cases where we - // *don't* check are: - // -- is_input_event(db_usage) - // -- ifExists_ == DB_OVERWRITE || DB_ADD_SUFFIX_OVERWRITE || DB_APPEND - // -- is_automatic_restart() && step == 0 (coming from validate) - if(m_ifDatabaseExists != DB_OVERWRITE && - m_ifDatabaseExists != DB_APPEND && - m_ifDatabaseExists != DB_ADD_SUFFIX_OVERWRITE && - !(step == 0 && observer->is_automatic_restart())) - { - abort_if_exists(filename, m_dbType, db_usage); - } - } - return filename; -} - -bool DynamicTopologyFileControl::abort_if_exists(const std::string &filename, - const std::string &db_type, - Ioss::DatabaseUsage db_usage) -{ - // Check whether file with same name as database already exists. If so, - // print error message and stop... - // At the current time, only check on processor 0 and assume if it doesn't exist - // there, then it doesn't exist on other processors. Or, if it doesn't exist on - // processor 0, then it doesn't matter if it doesn't exist on other processors - // since we don't have all pieces... - - bool exists = file_exists(filename, db_type, db_usage); - if (exists) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: The database file named '{} exists" - "and would be overwritten if the code continued.\n\n" - "Input options specified that this file *not* be overwritten,\n" - "\tso you must rename or remove this file and restart the code.\n", - filename); - IOSS_ERROR(errmsg); - } - return exists; -} - -Ioss::DatabaseIO * DynamicTopologyFileControl::clone_output_database(int steps) -{ - auto current_db = m_region->get_database(); - - if (current_db->is_input()) - return nullptr; - - const Ioss::PropertyManager& current_properties = current_db->get_property_manager(); - Ioss::NameList names; - current_properties.describe(&names); - - // Iterate through properties and transfer to new output database... - Ioss::NameList::const_iterator I; - for (I = names.begin(); I != names.end(); ++I) { - if (!current_properties.exists(*I)) - m_properties.add(current_properties.get(*I)); - } - - auto db_usage = current_db->usage(); - - std::string filename = construct_database_filename(steps, db_usage); - - Ioss::DatabaseIO *db = Ioss::IOFactory::create(m_dbType, filename, db_usage, - current_db->util().communicator(), - m_properties); - - if (nullptr == db) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: unable to create output database named '{}'" - " of type '{}'", filename, m_dbType); - IOSS_ERROR(errmsg); - } - - assert(db != nullptr); - if(!db->ok(true)) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: unable to validate output database named '{}'" - " of type '{}'", filename, m_dbType); - IOSS_ERROR(errmsg); - } - - db->set_field_separator(current_db->get_field_separator()); - db->set_surface_split_type(current_db->get_surface_split_type()); - db->set_maximum_symbol_length(current_db->maximum_symbol_length()); - db->set_int_byte_size_api(current_db->int_byte_size_data_size()); - - return db; -} - -template -void update_database_for_grouping_entities(const T& container, Ioss::DatabaseIO *db) -{ - for(auto * entity : container) { - Ioss::GroupingEntity* ge = dynamic_cast(entity); - assert(ge != nullptr); - - if(ge->type() == Ioss::SIDESET) { - Ioss::SideSet *sset = dynamic_cast(ge); - assert(sset != nullptr); - - sset->reset_database(db); - const auto &sblocks = sset->get_side_blocks(); - for (const auto &sblock : sblocks) { - sblock->reset_database(db); - } - } else { - ge->reset_database(db); - } - } -} - -bool DynamicTopologyFileControl::replace_output_database(Ioss::DatabaseIO *db) -{ - auto current_db = m_region->get_database(); - - if (current_db->is_input()) - return false; - - current_db->finalize_database(); - current_db->closeDatabase(); - delete current_db; - - m_region->reset_database(db); - db->set_region(m_region); - - update_database_for_grouping_entities(m_region->get_node_blocks(), db); - update_database_for_grouping_entities(m_region->get_edge_blocks(), db); - update_database_for_grouping_entities(m_region->get_face_blocks(), db); - update_database_for_grouping_entities(m_region->get_element_blocks(), db); - update_database_for_grouping_entities(m_region->get_sidesets(), db); - update_database_for_grouping_entities(m_region->get_nodesets(), db); - update_database_for_grouping_entities(m_region->get_edgesets(), db); - update_database_for_grouping_entities(m_region->get_facesets(), db); - update_database_for_grouping_entities(m_region->get_elementsets(), db); - update_database_for_grouping_entities(m_region->get_commsets(), db); - update_database_for_grouping_entities(m_region->get_structured_blocks(), db); - update_database_for_grouping_entities(m_region->get_assemblies(), db); - update_database_for_grouping_entities(m_region->get_blobs(), db); - - return true; -} - -void DynamicTopologyFileControl::clone_and_replace_output_database(int steps) -{ - auto db = clone_output_database(steps); - - if(nullptr != db) - replace_output_database(db); -} - -void DynamicTopologyFileControl::add_output_database_group(int steps) -{ - auto current_db = m_region->get_database(); - - std::ostringstream oss; - oss << "STEP-"; - oss << steps; - - current_db->release_memory(); - current_db->open_root_group(); - current_db->create_subgroup(oss.str()); -} - -} - - - - diff --git a/packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.h b/packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.h deleted file mode 100644 index be25390e3c..0000000000 --- a/packages/seacas/libraries/ioss/src/Ioss_DynamicTopology.h +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright(C) 2024 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. -// -// See packages/seacas/LICENSE for details - -#pragma once - -#include "Ioss_DatabaseIO.h" // for DatabaseIO -#include "Ioss_DBUsage.h" -#include "Ioss_ParallelUtils.h" // for ParallelUtils -#include "Ioss_PropertyManager.h" // for PropertyManager -#include -#include // for size_t, nullptr -#include // for int64_t - -#include "Ioss_CodeTypes.h" -#include "Ioss_Utils.h" -#include "ioss_export.h" - -#include // for ostream -#include -#include // for string, operator< - -namespace Ioss { - class Region; - - /*! The TopologyModified enumeration is used as an argument to the - * topology_modified() functions in io to - * specify the type of topology modification that has ocurred. The - * calls to topology_modified() are cumulative between - * output steps, so a call with TOPOLOGY_REORDER followed by a call - * with TOPOLOGY_SHUFFLE will do the right thing. Typical examples - * of when these would be used are: - * - TOPOLOGY_SAME: No change, but easier to call function than not. - * - TOPOLOGY_REORDER: Element Death which reorders the Registrars - * - TOPOLOGY_SHUFFLE: Load Balancing - * - TOPOLOGY_HADAPT: H-Adaptivity - * - TOPOLOGY_GHOST: Ghost nodes/edges/faces/elements created/destroyed - * - TOPOLOGY_GEOMETRY: Model data is modified, overlap removal. - * - TOPOLOGY_CREATEDELETE: Surface erosion, particle creation - * - TOPOLOGY_UNKNOWN: Something else, catchall option. - */ - enum TopologyModified { - TOPOLOGY_SAME = ( 0), //!< No change, also used for initialization - TOPOLOGY_REORDER = (1U << 0), //!< Data structures reordered on processor, no change between procs. - TOPOLOGY_SHUFFLE = (1U << 1), //!< Globally the same, data moved among processors. - TOPOLOGY_HADAPT = (1U << 2), //!< Elements split/combined; not moved cross-proc - TOPOLOGY_GHOST = (1U << 3), //!< Ghost entities created/destroyed - TOPOLOGY_GEOMETRY = (1U << 4), //!< Geometry (mesh coordinates) modified. Restart needs to know this. - TOPOLOGY_CREATEFACE = (1U << 5), //!< Face/Edge are created/deleted. - TOPOLOGY_CREATEELEM = (1U << 6), //!< Elements are created/deleted. - TOPOLOGY_CREATENODE = (1U << 7), //!< Nodes are created/deleted. - TOPOLOGY_UNKNOWN = (1U << 8), //!< Unknown change, recreate from scratch. - TOPOLOGY_AUXILIARY = (1U << 9), //!< An AUXILIARY relation was created/modified. - TOPOLOGY_CONSTRAINT = (1U << 10) //!< Contact constraints - }; - - enum class FileControlOption { - CONTROL_NONE, - CONTROL_AUTO_MULTI_FILE, - CONTROL_AUTO_SINGLE_FILE - }; - - class IOSS_EXPORT DynamicTopologyObserver - { - public: - DynamicTopologyObserver(Region *region) - : m_region(region) {} - DynamicTopologyObserver() {} - - virtual ~DynamicTopologyObserver() {} - - virtual void reset_topology_modification(); - virtual void set_topology_modification(unsigned int type); - virtual unsigned int get_topology_modification() const; - - virtual unsigned int get_cumulative_topology_modification() const; - virtual void set_cumulative_topology_modification(unsigned int type); - - int get_cumulative_topology_modification_field(); - - virtual bool is_topology_modified() const; - virtual bool is_automatic_restart() const { return false; } - virtual bool is_restart_requested() const { return false; } - - static const std::string topology_modification_change_name() {return std::string("CUMULATIVE_TOPOLOGY_MODIFICATION");} - - void register_region(Region *region); - Region* get_region() const { return m_region; } - - virtual void define_model(Region& region); - virtual void write_model(Region& region); - virtual void define_transient(Region& region); - - virtual FileControlOption get_control_option() const { return FileControlOption::CONTROL_AUTO_MULTI_FILE; } - - protected: - Region *m_region{nullptr}; - unsigned int m_topologyModification{TOPOLOGY_SAME}; - unsigned int m_cumulativeTopologyModification{TOPOLOGY_SAME}; - - bool m_automaticRestart{false}; - bool m_restartRequested{false}; - - void check_region() const; - IOSS_NODISCARD const ParallelUtils &util() const; - void synchronize_topology_modified_flags(); - }; - - class IOSS_EXPORT DynamicTopologyFileControl - { - public: - DynamicTopologyFileControl(Region *region, unsigned int fileCyclicCount, - IfDatabaseExistsBehavior &ifDatabaseExists, - unsigned int &dbChangeCount); - - void clone_and_replace_output_database(int steps=0); - void add_output_database_group(int steps=0); - - private: - Region *m_region{nullptr}; - std::string m_ioDB; - std::string m_dbType; - - PropertyManager m_properties; - - unsigned int m_fileCyclicCount; - IfDatabaseExistsBehavior &m_ifDatabaseExists; - unsigned int &m_dbChangeCount; - - IOSS_NODISCARD const ParallelUtils &util() const; - - std::string get_unique_filename(DatabaseUsage db_usage); - std::string construct_database_filename(int& step, DatabaseUsage db_usage); - bool file_exists(const std::string &filename, const std::string &db_type, DatabaseUsage db_usage); - bool abort_if_exists(const std::string &filename, const std::string &db_type, - DatabaseUsage db_usage); - - DatabaseIO * clone_output_database(int steps); - bool replace_output_database(DatabaseIO *db); - }; - -} // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C index 463040ed0f..e020d8dd37 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C +++ b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C @@ -94,8 +94,6 @@ Ioss::DatabaseIO *Ioss::IOFactory::create(const std::string &type, const std::st } else { auto my_props(properties); - my_props.add(Property("database_type", type)); - Ioss::ParallelUtils pu(communicator); pu.add_environment_properties(my_props); if (my_props.exists("SHOW_CONFIG")) { diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.C b/packages/seacas/libraries/ioss/src/Ioss_Region.C index 82850ffaa1..a3660c18f6 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.C @@ -20,9 +20,7 @@ #include "Ioss_FaceBlock.h" #include "Ioss_FaceSet.h" #include "Ioss_Field.h" -#include "Ioss_FileInfo.h" #include "Ioss_GroupingEntity.h" -#include "Ioss_IOFactory.h" #include "Ioss_NodeBlock.h" #include "Ioss_NodeSet.h" #include "Ioss_Property.h" @@ -45,11 +43,6 @@ #include #include -#include -#include -#include -#include - #include "Ioss_MeshType.h" #include "Ioss_ParallelUtils.h" @@ -102,30 +95,20 @@ namespace { return count; } - void update_database(Ioss::DatabaseIO *db, Ioss::GroupingEntity *entity) - { - entity->reset_database(db); - } - void update_database(const Ioss::Region *region, Ioss::GroupingEntity *entity) { - update_database(region->get_database(), entity); + entity->reset_database(region->get_database()); } - void update_database(Ioss::DatabaseIO *db, Ioss::SideSet *sset) + void update_database(const Ioss::Region *region, Ioss::SideSet *sset) { - sset->reset_database(db); + sset->reset_database(region->get_database()); const auto &blocks = sset->get_side_blocks(); for (const auto &block : blocks) { - block->reset_database(db); + block->reset_database(region->get_database()); } } - void update_database(const Ioss::Region *region, Ioss::SideSet *sset) - { - update_database(region->get_database(), sset); - } - constexpr unsigned numberOfBits(unsigned x) { return x < 2 ? x : 1 + numberOfBits(x >> 1); } size_t compute_hash(Ioss::GroupingEntity *entity, size_t which) @@ -365,9 +348,6 @@ namespace Ioss { properties.add(Property(this, "state_count", Property::INTEGER)); properties.add(Property(this, "current_state", Property::INTEGER)); properties.add(Property(this, "database_name", Property::STRING)); - - property_add(Property("base_filename", iodatabase->get_filename())); - property_add(Property("database_type", iodatabase->get_property_manager().get_optional("database_type", ""))); } Region::~Region() @@ -378,86 +358,63 @@ namespace Ioss { // Region owns all sub-grouping entities it contains... try { IOSS_FUNC_ENTER(m_); - reset_region(); + for (const auto &nb : nodeBlocks) { + delete (nb); + } - // Region owns the database pointer even though other entities use it. - GroupingEntity::really_delete_database(); - } - catch (...) { - } - } + for (const auto &eb : edgeBlocks) { + delete (eb); + } - void Region::reset_region() - { - for (const auto &nb : nodeBlocks) { - delete (nb); - } - nodeBlocks.clear(); + for (const auto &fb : faceBlocks) { + delete (fb); + } - for (const auto &eb : edgeBlocks) { - delete (eb); - } - edgeBlocks.clear(); + for (const auto &eb : elementBlocks) { + delete (eb); + } - for (const auto &fb : faceBlocks) { - delete (fb); - } - faceBlocks.clear(); + for (const auto &sb : structuredBlocks) { + delete (sb); + } - for (const auto &eb : elementBlocks) { - delete (eb); - } - elementBlocks.clear(); + for (const auto &ss : sideSets) { + delete (ss); + } - for (const auto &sb : structuredBlocks) { - delete (sb); - } - structuredBlocks.clear(); + for (const auto &ns : nodeSets) { + delete (ns); + } - for (const auto &ss : sideSets) { - delete (ss); - } - sideSets.clear(); + for (const auto &es : edgeSets) { + delete (es); + } - for (const auto &ns : nodeSets) { - delete (ns); - } - nodeSets.clear(); + for (const auto &fs : faceSets) { + delete (fs); + } - for (const auto &es : edgeSets) { - delete (es); - } - edgeSets.clear(); + for (const auto &es : elementSets) { + delete (es); + } - for (const auto &fs : faceSets) { - delete (fs); - } - faceSets.clear(); + for (const auto &cs : commSets) { + delete (cs); + } - for (const auto &es : elementSets) { - delete (es); - } - elementSets.clear(); + for (const auto &as : assemblies) { + delete (as); + } - for (const auto &cs : commSets) { - delete (cs); - } - commSets.clear(); + for (const auto &bl : blobs) { + delete (bl); + } - for (const auto &as : assemblies) { - delete (as); + // Region owns the database pointer even though other entities use it. + GroupingEntity::really_delete_database(); } - assemblies.clear(); - - for (const auto &bl : blobs) { - delete (bl); + catch (...) { } - blobs.clear(); - - stateTimes.clear(); - - currentState = -1; - stateCount = 0; } void Region::delete_database() { GroupingEntity::really_delete_database(); } @@ -695,27 +652,6 @@ namespace Ioss { success = set_state(new_state); } else { - bool has_output_observer = topologyObserver && !get_database()->is_input(); - - if(new_state == STATE_DEFINE_MODEL) { - if(has_output_observer && (topologyObserver->get_control_option() == FileControlOption::CONTROL_AUTO_SINGLE_FILE)) { - if(!modelWritten) { - int steps = get_property("state_count").get_int(); - bool force_addition = true; - add_output_database_group(steps, force_addition); - } - } - } else if(new_state == STATE_TRANSIENT) { - if(has_output_observer && topologyObserver->is_topology_modified()) { - int steps = get_property("state_count").get_int(); - start_new_output_database_entry(steps); - - topologyObserver->define_model(*this); - topologyObserver->write_model(*this); - topologyObserver->define_transient(*this); - topologyObserver->reset_topology_modification(); - } - } switch (get_state()) { case STATE_CLOSED: // Make sure we can go to the specified state. @@ -849,12 +785,6 @@ namespace Ioss { else if (current_state == STATE_DEFINE_TRANSIENT) { transientDefined = true; } - else if (current_state == STATE_MODEL) { - modelWritten = true; - } - else if (current_state == STATE_TRANSIENT) { - transientWritten = true; - } return success; } @@ -2811,165 +2741,4 @@ namespace Ioss { } } - void Region::register_mesh_modification_observer(std::shared_ptr observer) - { - if(observer && observer->get_control_option() == FileControlOption::CONTROL_AUTO_SINGLE_FILE) { - const Ioss::PropertyManager &properties = get_database()->get_property_manager(); - if(!properties.exists("ENABLE_FILE_GROUPS")) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: File groups are not enabled in the database file '{}'.\n", - get_database()->get_filename()); - IOSS_ERROR(errmsg); - } - } - - topologyObserver = observer; - topologyObserver->register_region(this); - } - - void Region::start_new_output_database_entry(int steps) - { - if (get_database()->is_input()) - return; - - if(!topologyObserver) - return; - - switch(topologyObserver->get_control_option()) { - case FileControlOption::CONTROL_AUTO_MULTI_FILE: - clone_and_replace_output_database(steps); - break; - case FileControlOption::CONTROL_AUTO_SINGLE_FILE: - add_output_database_group(steps); - break; - case FileControlOption::CONTROL_NONE: - default: - return; - break; - } - } - - void Region::add_output_database_group(int steps, bool force_addition) - { - if (get_database()->is_input()) - return; - - const Ioss::PropertyManager &properties = get_database()->get_property_manager(); - if(!properties.exists("ENABLE_FILE_GROUPS")) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: File groups are not enabled in the database file '{}'.\n", - get_database()->get_filename()); - IOSS_ERROR(errmsg); - } - - if(topologyObserver && (topologyObserver->get_control_option() == FileControlOption::CONTROL_AUTO_MULTI_FILE)) { - std::ostringstream errmsg; - fmt::print(errmsg, - "ERROR: TopologyObserver for database file '{}' does not support file groups.\n", - get_database()->get_filename()); - IOSS_ERROR(errmsg); - } - - int state = steps; - if ((topologyObserver && topologyObserver->is_topology_modified()) || force_addition) { - // Determine how many steps have been written already... - state = get_property("state_count").get_int(); - - if (state == 0) - state = steps; - - // See if this is a continuation database... - if (property_exists("state_offset")) - state += get_property("state_offset").get_int(); - - state++; // For the state we are going to write. - - reset_region(); - DynamicTopologyFileControl fileControl(this, fileCyclicCount, ifDatabaseExists, dbChangeCount); - fileControl.add_output_database_group(state); - } - } - - void Region::clone_and_replace_output_database(int steps) - { - if (get_database()->is_input()) - return; - - if(!topologyObserver) - return; - - int state = steps; - if (topologyObserver->is_topology_modified() || fileCyclicCount > 0) { - // Determine how many steps have been written already... - state = get_property("state_count").get_int(); - - // Needed for automatic restart... The current database has not - // been written to, but we want to open a new one instead of - // (possibly) overwriting the current one... - // If this is not an automatic restart, then we don't need a new database... - if (state == 0 && topologyObserver->is_automatic_restart()) - return; - - if (topologyObserver->is_automatic_restart() && ifDatabaseExists == Ioss::DB_APPEND) - return; - - if (state == 0) - state = steps; - - // See if this is a continutation database... - if (property_exists("state_offset")) - state += get_property("state_offset").get_int(); - - state++; // For the state we are going to write. - - reset_region(); - DynamicTopologyFileControl fileControl(this, fileCyclicCount, ifDatabaseExists, dbChangeCount); - fileControl.clone_and_replace_output_database(state); - } - } - - bool Region::load_group_mesh(const std::string &group_name) - { - // Check name for '/' which is not allowed since it is the - // separator character in a full group path - if (group_name.find('/') != std::string::npos) { - std::ostringstream errmsg; - fmt::print(errmsg, "ERROR: Invalid group name '{}' contains a '/' which is not allowed.\n", - group_name); - IOSS_ERROR(errmsg); - } - - DatabaseIO *iodatabase = get_database(); - - if (!iodatabase->is_input()) - return false; - - if(!iodatabase->open_root_group()) - return false; - - if(!iodatabase->open_group(group_name)) - return false; - - reset_region(); - iodatabase->release_memory(); - - Region::set_state(STATE_CLOSED); - modelDefined = false; - transientDefined = false; - - Region::begin_mode(STATE_DEFINE_MODEL); - iodatabase->read_meta_data(); - Region::end_mode(STATE_DEFINE_MODEL); - if (iodatabase->open_create_behavior() != Ioss::DB_APPEND && - iodatabase->open_create_behavior() != Ioss::DB_MODIFY) { - modelDefined = true; - transientDefined = true; - Region::begin_mode(STATE_READONLY); - } - - return true; - } - } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.h b/packages/seacas/libraries/ioss/src/Ioss_Region.h index 9a7f27754b..730693ad61 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.h @@ -8,8 +8,6 @@ #include "Ioss_CoordinateFrame.h" // for CoordinateFrame #include "Ioss_DatabaseIO.h" // for DatabaseIO -#include "Ioss_DBUsage.h" -#include "Ioss_DynamicTopology.h" #include "Ioss_EntityType.h" // for EntityType, etc #include "Ioss_Field.h" #include "Ioss_GroupingEntity.h" // for GroupingEntity @@ -30,7 +28,6 @@ #include // for less #include // for ostream #include // for map, map<>::value_compare -#include #include #include // for string, operator< #include // for pair @@ -58,7 +55,6 @@ namespace Ioss { namespace Ioss { class CoordinateFrame; - enum class MeshType; using AssemblyContainer = std::vector; @@ -284,28 +280,7 @@ namespace Ioss { const std::vector &entity_container, std::vector &field_data) const; - void register_mesh_modification_observer(std::shared_ptr observer); - std::shared_ptr get_mesh_modification_observer() const { return topologyObserver; } - - void start_new_output_database_entry(int steps=0); - - void set_topology_change_count(unsigned int new_count) {dbChangeCount = new_count;} - unsigned int get_topology_change_count() {return dbChangeCount;} - - void set_file_cyclic_count(unsigned int new_count) {fileCyclicCount = new_count;} - unsigned int get_file_cyclic_count() {return fileCyclicCount;} - - void set_if_database_exists_behavior(IfDatabaseExistsBehavior if_exists) {ifDatabaseExists = if_exists;} - - bool model_is_written() const { return modelWritten; } - bool transient_is_written() const { return transientWritten; } - - bool load_group_mesh(const std::string &group_name); - protected: - void clone_and_replace_output_database(int steps=0); - void add_output_database_group(int steps=0, bool force_addition=false); - int64_t internal_get_field_data(const Field &field, void *data, size_t data_size = 0) const override; @@ -331,7 +306,6 @@ namespace Ioss { bool end_mode_nl(State current_state); void delete_database() override; - void reset_region(); mutable std::map aliases_; ///< Stores alias mappings @@ -358,15 +332,6 @@ namespace Ioss { mutable int stateCount{0}; bool modelDefined{false}; bool transientDefined{false}; - - std::shared_ptr topologyObserver; - - unsigned int dbChangeCount{1}; //!< Used to track number of topology changes. - unsigned int fileCyclicCount{0}; //!< For cycling file-A, file-B, file-C, ..., File-A, typically restart only. - IfDatabaseExistsBehavior ifDatabaseExists{DB_OVERWRITE}; - - bool modelWritten{false}; - bool transientWritten{false}; }; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C index 5733bdf694..d56ed2194c 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C @@ -18,7 +18,6 @@ #include #include #include -#include #include "Ioex_Utils.h" #include "Ioss_Assembly.h" @@ -88,8 +87,6 @@ namespace { template void write_attribute_names(int exoid, ex_entity_type type, const std::vector &entities); - void query_groups(int exoid, Ioss::NameList& names, bool return_full_names); - class AssemblyTreeFilter { public: @@ -502,40 +499,6 @@ namespace Ioex { ex_set_max_name_length(m_exodusFilePtr, maximumNameLength); } - bool BaseDatabaseIO::open_root_group_nl() - { - // Get existing file pointer... - bool success = false; - - int exoid = get_file_pointer(); - - int group_name_length = ex_inquire_int(exoid, EX_INQ_GROUP_NAME_LEN); - std::vector group_name(group_name_length+1, '\0'); - - // Get name of this group... - int idum; - float rdum; - int ierr = ex_inquire(exoid, EX_INQ_GROUP_NAME, &idum, &rdum, group_name.data()); - if (ierr < 0) { - std::ostringstream errmsg; - fmt::print(errmsg, "ERROR: Could not open root group of group named '{}' in file '{}'.\n", m_groupName, - get_filename()); - IOSS_ERROR(errmsg); - } - - m_groupName = std::string(group_name.data()); - m_exodusFilePtr = ex_inquire_int(exoid, EX_INQ_GROUP_ROOT); - - if (m_exodusFilePtr < 0) { - std::ostringstream errmsg; - fmt::print(errmsg, "ERROR: Could not open group named '{}' in file '{}'.\n", m_groupName, - get_filename()); - IOSS_ERROR(errmsg); - } - success = true; - return success; - } - bool BaseDatabaseIO::open_group_nl(const std::string &group_name) { // Get existing file pointer... @@ -3217,41 +3180,6 @@ namespace Ioex { // Write coordinate frame data... write_coordinate_frames(get_file_pointer(), get_region()->get_coordinate_frames()); } - - - Ioss::NameList BaseDatabaseIO::groups_describe_nl(bool return_full_names) - { - Ioss::SerializeIO serializeIO_(this); - - Ioss::NameList names; - int group_root = ex_inquire_int(get_file_pointer(), EX_INQ_GROUP_ROOT); - query_groups(group_root, names, return_full_names); - - return names; - } - - void BaseDatabaseIO::release_memory_nl() - { - Ioss::DatabaseIO::release_memory_nl(); - - ids_.clear(); - m_groupCount.clear(); - - nodeCmapIds.clear(); - nodeCmapNodeCnts.clear(); - elemCmapIds.clear(); - elemCmapElemCnts.clear(); - - m_truthTable.clear(); - m_variables.clear(); - m_reductionVariables.clear(); - - m_reductionValues.clear(); - - nodeConnectivityStatus.clear(); - - activeNodeSetNodesIndex.clear(); - } } // namespace Ioex namespace { @@ -3553,41 +3481,4 @@ namespace { } #endif } - - void query_groups(int exoid, Ioss::NameList& names, bool return_full_names) - { - int idum; - float rdum; - - int group_name_length = ex_inquire_int(exoid, EX_INQ_GROUP_NAME_LEN); - std::vector group_name(group_name_length+1, '\0'); - - // Get name of this group... - int ierr = ex_inquire(exoid, EX_INQ_GROUP_NAME, &idum, &rdum, group_name.data()); - if (ierr < 0) { - Ioex::exodus_error(exoid, __LINE__, __func__, __FILE__); - } - - if(return_full_names) { - std::fill(group_name.begin(), group_name.end(), '\0'); - ierr = ex_inquire(exoid, EX_INQ_FULL_GROUP_NAME, &idum, &rdum, group_name.data()); - if (ierr < 0) { - Ioex::exodus_error(exoid, __LINE__, __func__, __FILE__); - } - names.push_back(std::string(group_name.data())); - } else { - names.push_back(std::string(group_name.data())); - } - - int num_children = ex_inquire_int(exoid, EX_INQ_NUM_CHILD_GROUPS); - std::vector children(num_children); - ierr = ex_get_group_ids(exoid, nullptr, Data(children)); - if (ierr < 0) { - Ioex::exodus_error(exoid, __LINE__, __func__, __FILE__); - } - - for (int i = 0; i < num_children; i++) { - query_groups(children[i], names, return_full_names); - } - } } // namespace diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h index 11174e6052..9521e11cd6 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h @@ -99,12 +99,8 @@ namespace Ioex { IOSS_NODISCARD bool ok_nl(bool write_message = false, std::string *error_message = nullptr, int *bad_count = nullptr) const override; - void release_memory_nl() override; - - bool open_root_group_nl() override; bool open_group_nl(const std::string &group_name) override; bool create_subgroup_nl(const std::string &group_name) override; - Ioss::NameList groups_describe_nl(bool return_full_names) override; bool begin_nl(Ioss::State state) override; bool end_nl(Ioss::State state) override; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C index 12ac92d9e6..d922e6fafd 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C @@ -17,7 +17,6 @@ #include #include #include -#include #include "Ioss_BasisVariableType.h" #include "Ioss_CoordinateFrame.h" @@ -617,7 +616,7 @@ namespace Ioex { // Try to decode an id from the name. std::string name_string = entity->get_property(prop_name).get_string(); std::string type_name = entity->short_type_string(); - if (strncasecmp(type_name.c_str(), name_string.c_str(), type_name.size()) == 0) { + if (std::strncmp(type_name.c_str(), name_string.c_str(), type_name.size()) == 0) { id = extract_id(name_string); if (id <= 0) { id = 1; diff --git a/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt b/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt index db5ff09522..17a7bbb440 100644 --- a/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt +++ b/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt @@ -14,17 +14,6 @@ TRIBITS_ADD_EXECUTABLE( SOURCES unitMain.C UnitTestElementBlockBatchRead.C ) -TRIBITS_ADD_EXECUTABLE( - Utst_dynamictopology - SOURCES unitMain.C UnitTestDynamicTopology.C -) - -TRIBITS_ADD_TEST( - Utst_dynamictopology - NAME Utst_dynamictopology - NUM_MPI_PROCS 1 -) - TRIBITS_ADD_TEST( Utst_blockbatchread NAME Utst_blockbatchread diff --git a/packages/seacas/libraries/ioss/src/unit_tests/UnitTestDynamicTopology.C b/packages/seacas/libraries/ioss/src/unit_tests/UnitTestDynamicTopology.C deleted file mode 100644 index 150ff08038..0000000000 --- a/packages/seacas/libraries/ioss/src/unit_tests/UnitTestDynamicTopology.C +++ /dev/null @@ -1,679 +0,0 @@ -// Copyright(C) 1999-2020, 2022 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. -// -// See packages/seacas/LICENSE for details - -#include -#include - -#ifdef SEACAS_HAVE_MPI -#include "mpi.h" -#endif -#include "gtest/gtest.h" - -#include -#include -#include -#include -#include - -#include // for unlink - -#include "Ionit_Initializer.h" -#include "Ioss_DBUsage.h" -#include "Ioss_DatabaseIO.h" // for DatabaseIO -#include "Ioss_Field.h" // for Field, etc -#include "Ioss_IOFactory.h" -#include "Ioss_ParallelUtils.h" -#include "Ioss_Property.h" -#include "Ioss_FileInfo.h" -#include "Ioss_ElementBlock.h" -#include "Ioss_NodeBlock.h" -#include "Ioss_ParallelUtils.h" -#include "Ioss_Region.h" - -#include "Ioss_Utils.h" - -#include "exodus/Ioex_DatabaseIO.h" - -namespace { -std::string get_many_block_mesh_desc(unsigned numBlocks) -{ - std::ostringstream oss; - std::vector elementIds(numBlocks); - std::iota(elementIds.begin(), elementIds.end(), 1); - - unsigned proc = 0; - for (unsigned i = 0; i < numBlocks; ++i) { - unsigned elemId = elementIds[i]; - unsigned firstNodeId = i * 4 + 1; - oss << proc << "," << elemId << ",HEX_8,"; - for (unsigned node = firstNodeId; node < firstNodeId + 8; ++node) { - oss << node << ","; - } - unsigned blockId = i + 1; - oss << "block_" << blockId; - - if (i < numBlocks - 1) { - oss << "\n"; - } - - proc++; - } - - oss << "|coordinates:"; - - std::vector planeCoords = {0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0}; - - for (double coord : planeCoords) { - oss << coord << ","; - } - - for (unsigned i = 1; i <= numBlocks; ++i) { - for (unsigned point = 0; point < 4; ++point) { - planeCoords[3 * point + 2] += 1; - } - - for (double coord : planeCoords) { - oss << coord << ","; - } - } - - return oss.str(); -} - -void define_model(const Ioss::Region &i_region, Ioss::Region &o_region) -{ - Ioss::DatabaseIO *o_database = o_region.get_database(); - - o_region.begin_mode(Ioss::STATE_DEFINE_MODEL); - - auto& nodeblocks = o_region.get_node_blocks(); - - Ioss::NodeBlock *i_nb = i_region.get_node_blocks()[0]; - int64_t spatial_dim = 3; - int64_t num_nodes = i_nb->entity_count(); - Ioss::NodeBlock *o_nb = new Ioss::NodeBlock(o_database, "nodeblock_1", num_nodes, spatial_dim); - o_region.add(o_nb); - - for (Ioss::ElementBlock *i_eb : i_region.get_element_blocks()) { - Ioss::ElementBlock *o_eb = new Ioss::ElementBlock( - o_database, i_eb->name(), i_eb->topology()->name(), i_eb->entity_count()); - o_eb->property_add(i_eb->get_property("id")); - o_region.add(o_eb); - } - - o_region.end_mode(Ioss::STATE_DEFINE_MODEL); -} - -void write_model(const Ioss::Region &i_region, Ioss::Region &o_region) -{ - Ioss::NodeBlock *i_nb = i_region.get_node_blocks()[0]; - Ioss::NodeBlock *o_nb = o_region.get_node_blocks()[0]; - - o_region.begin_mode(Ioss::STATE_MODEL); - std::vector coordinates; - std::vector node_ids; - i_nb->get_field_data("ids", node_ids); - i_nb->get_field_data("mesh_model_coordinates", coordinates); - - o_nb->put_field_data("ids", node_ids); - o_nb->put_field_data("mesh_model_coordinates", coordinates); - - for (Ioss::ElementBlock *i_eb : i_region.get_element_blocks()) { - Ioss::ElementBlock *o_eb = o_region.get_element_block(i_eb->name()); - std::vector elem_ids; - std::vector connectivity; - - i_eb->get_field_data("ids", elem_ids); - i_eb->get_field_data("connectivity", connectivity); - - o_eb->put_field_data("ids", elem_ids); - o_eb->put_field_data("connectivity", connectivity); - } - - o_region.end_mode(Ioss::STATE_MODEL); -} - -void define_transient(const Ioss::Region &i_region, Ioss::Region &o_region, - const std::string &elemFieldName) -{ - o_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT); - - for (Ioss::ElementBlock *o_eb : o_region.get_element_blocks()) { - size_t num_elem = o_eb->get_property("entity_count").get_int(); - std::string storage = "scalar"; - - Ioss::Field field(elemFieldName, Ioss::Field::REAL, storage, 1, Ioss::Field::Field::TRANSIENT, - num_elem); - o_eb->field_add(field); - } - o_region.end_mode(Ioss::STATE_DEFINE_TRANSIENT); -} - -int write_transient(Ioss::Region &o_region, const std::string &elemFieldName, const double time) -{ - o_region.begin_mode(Ioss::STATE_TRANSIENT); - int step = o_region.add_state(time); - o_region.begin_state(step); - - for (Ioss::ElementBlock *o_eb : o_region.get_element_blocks()) { - size_t num_elem = o_eb->get_property("entity_count").get_int(); - - std::vector field_data(num_elem); - std::vector elem_ids; - - o_eb->get_field_data("ids", elem_ids); - for (size_t i = 0; i < elem_ids.size(); i++) { - field_data[i] = (double)elem_ids[i] + 100*time; - } - - o_eb->put_field_data(elemFieldName, field_data); - } - - o_region.end_state(step); - o_region.end_mode(Ioss::STATE_TRANSIENT); - - return step; -} - -class Observer : public Ioss::DynamicTopologyObserver -{ -public: - Observer(Ioss::Region& inputRegion_, - const std::string &elemFieldName_, - const Ioss::FileControlOption fileControlOption_) - : inputRegion(inputRegion_) - , elemFieldName(elemFieldName_) - , fileControlOption(fileControlOption_) - {} - - virtual ~Observer() {} - - void define_model(Ioss::Region& region) override - { - ::define_model(inputRegion, region); - } - - void write_model(Ioss::Region& region) override - { - ::write_model(inputRegion, region); - } - - void define_transient(Ioss::Region& region) override - { - ::define_transient(inputRegion, region, elemFieldName); - } - - Ioss::FileControlOption get_control_option() const - { - return fileControlOption; - } - -private: - Observer(); - - Ioss::Region& inputRegion; - const std::string elemFieldName; - Ioss::FileControlOption fileControlOption; -}; - -void run_simple_topology_change(const Ioss::Region& i_region, - Ioss::Region &o_region, - std::shared_ptr observer, - const std::string &elemFieldName) -{ - define_model(i_region, o_region); - write_model(i_region, o_region); - - define_transient(i_region, o_region, elemFieldName); - - double time = 0.0; - write_transient(o_region, elemFieldName, time); - - auto min_result1 = o_region.get_min_time(); - EXPECT_EQ(1, min_result1.first); - EXPECT_NEAR(0.0, min_result1.second, 1.0e-6); - - auto max_result1 = o_region.get_max_time(); - EXPECT_EQ(1, max_result1.first); - EXPECT_NEAR(0.0, max_result1.second, 1.0e-6); - - observer->set_topology_modification(Ioss::TOPOLOGY_UNKNOWN); - - time = 1.0; - write_transient(o_region, elemFieldName, time); - - auto min_result2 = o_region.get_min_time(); - EXPECT_EQ(1, min_result2.first); - EXPECT_NEAR(1.0, min_result2.second, 1.0e-6); - - auto max_result2 = o_region.get_max_time(); - EXPECT_EQ(1, max_result2.first); - EXPECT_NEAR(1.0, max_result2.second, 1.0e-6); - - observer->set_topology_modification(Ioss::TOPOLOGY_SAME); - - time = 2.0; - write_transient(o_region, elemFieldName, time); - - auto min_result3 = o_region.get_min_time(); - EXPECT_EQ(1, min_result3.first); - EXPECT_NEAR(1.0, min_result3.second, 1.0e-6); - - auto max_result3 = o_region.get_max_time(); - EXPECT_EQ(2, max_result3.first); - EXPECT_NEAR(2.0, max_result3.second, 1.0e-6); -} - -void cleanup_multi_files(const std::string &outFile) -{ - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - std::string file1 = Ioss::Utils::decode_filename(outFile, util.parallel_rank(), util.parallel_size()); - unlink(file1.c_str()); - - std::string file2 = Ioss::Utils::decode_filename(outFile + "-s0002", util.parallel_rank(), util.parallel_size()); - unlink(file2.c_str()); -} - -void run_multi_file_simple_topology_change(const std::string &elemFieldName, const std::string &outFile) -{ - Ioss::Init::Initializer io; - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - int numBlocks = util.parallel_size(); - - std::string meshDesc = get_many_block_mesh_desc(numBlocks); - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - auto fileControlOption = Ioss::FileControlOption::CONTROL_AUTO_MULTI_FILE; - auto observer = std::make_shared(i_region, elemFieldName, fileControlOption); - o_region.register_mesh_modification_observer(observer); - - run_simple_topology_change(i_region, o_region, observer, elemFieldName); -} - -TEST(TestDynamicWrite, multi_file_simple_topology_modification) -{ - std::string outFile("multiFileManyBlocks.g"); - std::string elemFieldName = "elem_field"; - - cleanup_multi_files(outFile); - run_multi_file_simple_topology_change(elemFieldName, outFile); - cleanup_multi_files(outFile); -} - -void cleanup_single_file(const std::string &outFile) -{ - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - std::string file1 = Ioss::Utils::decode_filename(outFile, util.parallel_rank(), util.parallel_size()); - unlink(file1.c_str()); -} - -void run_single_file_simple_topology_change(const std::string &elemFieldName, const std::string &outFile) -{ - Ioss::Init::Initializer io; - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - int numBlocks = util.parallel_size(); - - std::string meshDesc = get_many_block_mesh_desc(numBlocks); - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - propertyManager.add(Ioss::Property("ENABLE_FILE_GROUPS", 1)); - propertyManager.add(Ioss::Property("APPEND_OUTPUT", Ioss::DB_APPEND_GROUP)); - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - auto fileControlOption = Ioss::FileControlOption::CONTROL_AUTO_SINGLE_FILE; - auto observer = std::make_shared(i_region, elemFieldName, fileControlOption); - o_region.register_mesh_modification_observer(observer); - - run_simple_topology_change(i_region, o_region, observer, elemFieldName); - - Ioss::NameList names = o_database->groups_describe(false); - Ioss::NameList full_names = o_database->groups_describe(true); - - std::vector gold_names{"/", "STEP-1", "STEP-2"}; - std::vector gold_full_names{"/", "/STEP-1", "/STEP-2"}; - - EXPECT_EQ(gold_names, names); - EXPECT_EQ(gold_full_names, full_names); -} - -TEST(TestDynamicWrite, single_file_simple_topology_modification) -{ - std::string outFile("singleFileManyBlocks.g"); - std::string elemFieldName = "elem_field"; - - cleanup_single_file(outFile); - run_single_file_simple_topology_change(elemFieldName, outFile); - cleanup_single_file(outFile); -} - -TEST(TestDynamicWrite, single_file_groups_not_enabled) -{ - Ioss::Init::Initializer io; - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - int numBlocks = util.parallel_size(); - if(numBlocks > 1) GTEST_SKIP(); - - std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8,block_1" - "|coordinates:0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1"; - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - std::string outFile("singleFileGroupsNotEnabled.g"); - std::string elemFieldName = "elem_field"; - cleanup_single_file(outFile); - - // Need the line below to allow this to pass - // propertyManager.add(Ioss::Property("ENABLE_FILE_GROUPS", 1)); - propertyManager.add(Ioss::Property("APPEND_OUTPUT", Ioss::DB_APPEND_GROUP)); - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - auto fileControlOption = Ioss::FileControlOption::CONTROL_AUTO_SINGLE_FILE; - auto observer = std::make_shared(i_region, elemFieldName, fileControlOption); - EXPECT_THROW(o_region.register_mesh_modification_observer(observer), std::runtime_error); - cleanup_single_file(outFile); -} - -TEST(TestDynamicWrite, create_subgroup_with_file_reopen) -{ - std::string outFile("subgroupManyBlocks.g"); - std::string elemFieldName = "elem_field"; - - Ioss::Init::Initializer io; - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - std::string file1 = Ioss::Utils::decode_filename(outFile, util.parallel_rank(), util.parallel_size()); - unlink(file1.c_str()); - - int numBlocks = util.parallel_size(); - if(numBlocks > 1) GTEST_SKIP(); - - std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8,block_1" - "|coordinates:0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1"; - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - { - propertyManager.add(Ioss::Property("ENABLE_FILE_GROUPS", 1)); - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - o_database->create_subgroup("GROUP_1"); - } - - { - propertyManager.add(Ioss::Property("APPEND_OUTPUT", Ioss::DB_APPEND_GROUP)); - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - // Group pointer is still at root level - o_database->create_subgroup("GROUP_2"); - - Ioss::NameList names = o_database->groups_describe(false); - Ioss::NameList full_names = o_database->groups_describe(true); - - std::vector gold_names{"/", "GROUP_1", "GROUP_2"}; - std::vector gold_full_names{"/", "/GROUP_1", "/GROUP_2"}; - - EXPECT_EQ(gold_names, names); - EXPECT_EQ(gold_full_names, full_names); - } - - unlink(file1.c_str()); -} - -TEST(TestDynamicWrite, create_subgroup_with_file_persistence_and_child_group) -{ - std::string outFile("subgroupManyBlocks.g"); - std::string elemFieldName = "elem_field"; - - Ioss::Init::Initializer io; - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - std::string file1 = Ioss::Utils::decode_filename(outFile, util.parallel_rank(), util.parallel_size()); - unlink(file1.c_str()); - - int numBlocks = util.parallel_size(); - if(numBlocks > 1) GTEST_SKIP(); - - std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8,block_1" - "|coordinates:0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1"; - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - { - propertyManager.add(Ioss::Property("ENABLE_FILE_GROUPS", 1)); - propertyManager.add(Ioss::Property("APPEND_OUTPUT", Ioss::DB_APPEND_GROUP)); - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - o_database->create_subgroup("GROUP_1"); - - // Group pointer is at "GROUP_1" ... "GROUP_2" is a child - o_database->create_subgroup("GROUP_2"); - - Ioss::NameList names = o_database->groups_describe(false); - Ioss::NameList full_names = o_database->groups_describe(true); - - std::vector gold_names{"/", "GROUP_1", "GROUP_2"}; - std::vector gold_full_names{"/", "/GROUP_1", "/GROUP_1/GROUP_2"}; - - EXPECT_EQ(gold_names, names); - EXPECT_EQ(gold_full_names, full_names); - } - - unlink(file1.c_str()); -} - -TEST(TestDynamicWrite, create_subgroup_with_file_persistence_and_no_child_group) -{ - std::string outFile("subgroupManyBlocks.g"); - std::string elemFieldName = "elem_field"; - - Ioss::Init::Initializer io; - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - std::string file1 = Ioss::Utils::decode_filename(outFile, util.parallel_rank(), util.parallel_size()); - unlink(file1.c_str()); - - int numBlocks = util.parallel_size(); - if(numBlocks > 1) GTEST_SKIP(); - - std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8,block_1" - "|coordinates:0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1"; - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - { - propertyManager.add(Ioss::Property("ENABLE_FILE_GROUPS", 1)); - propertyManager.add(Ioss::Property("APPEND_OUTPUT", Ioss::DB_APPEND_GROUP)); - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, - Ioss::ParallelUtils::comm_world(), - propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - o_database->create_subgroup("GROUP_1"); - - // Group pointer is reset to root group - EXPECT_TRUE(o_database->open_root_group()); - o_database->create_subgroup("GROUP_2"); - - Ioss::NameList names = o_database->groups_describe(false); - Ioss::NameList full_names = o_database->groups_describe(true); - - std::vector gold_names{"/", "GROUP_1", "GROUP_2"}; - std::vector gold_full_names{"/", "/GROUP_1", "/GROUP_2"}; - - EXPECT_EQ(gold_names, names); - EXPECT_EQ(gold_full_names, full_names); - } - - unlink(file1.c_str()); -} - -void test_single_file_simple_topology_change_data(Ioss::Region& i_region, const std::string& elemFieldName, - int gold_step, double gold_time) -{ - i_region.begin_state(gold_step); - for (Ioss::ElementBlock *i_eb : i_region.get_element_blocks()) { - size_t num_elem = i_eb->get_property("entity_count").get_int(); - - std::vector field_data(num_elem); - std::vector elem_ids; - - i_eb->get_field_data(elemFieldName, field_data); - i_eb->get_field_data("ids", elem_ids); - - for (size_t i = 0; i < elem_ids.size(); i++) { - double gold_value = (double)elem_ids[i] + 100*gold_time; - EXPECT_NEAR(gold_value, field_data[i], 1.0e-6); - } - } -} - -void read_and_test_single_file_simple_topology_change(const std::string& elemFieldName, const std::string& outFile) -{ - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO *i_database = Ioss::IOFactory::create("exodus", outFile, Ioss::READ_RESTART, - Ioss::ParallelUtils::comm_world(), - propertyManager); - - Ioss::NameList names = i_database->groups_describe(false); - Ioss::NameList full_names = i_database->groups_describe(true); - - std::vector gold_names{"/", "STEP-1", "STEP-2"}; - std::vector gold_full_names{"/", "/STEP-1", "/STEP-2"}; - - EXPECT_EQ(gold_names, names); - EXPECT_EQ(gold_full_names, full_names); - - EXPECT_TRUE(i_database->open_group("STEP-1")); - - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - double gold_time = 0.0; - int gold_step = 1; - auto min_result1 = i_region.get_min_time(); - EXPECT_EQ(gold_step, min_result1.first); - EXPECT_NEAR(gold_time, min_result1.second, 1.0e-6); - - auto max_result1 = i_region.get_max_time(); - EXPECT_EQ(gold_step, max_result1.first); - EXPECT_NEAR(gold_time, max_result1.second, 1.0e-6); - test_single_file_simple_topology_change_data(i_region, elemFieldName, gold_step, gold_time); - - EXPECT_TRUE(i_region.load_group_mesh("STEP-2")); - - double gold_min_time = 1.0; - int gold_min_step = 1; - auto min_result2 = i_region.get_min_time(); - EXPECT_EQ(gold_min_step, min_result2.first); - EXPECT_NEAR(gold_min_time, min_result2.second, 1.0e-6); - test_single_file_simple_topology_change_data(i_region, elemFieldName, gold_min_step, gold_min_time); - - auto max_result2 = i_region.get_max_time(); - double gold_max_time = 2.0; - int gold_max_step = 2; - EXPECT_EQ(gold_max_step, max_result2.first); - EXPECT_NEAR(gold_max_time, max_result2.second, 1.0e-6); - test_single_file_simple_topology_change_data(i_region, elemFieldName, gold_max_step, gold_max_time); -} - -TEST(TestDynamicRead, single_file_simple_topology_modification) -{ - std::string outFile("singleFileManyBlocks.g"); - std::string elemFieldName = "elem_field"; - - cleanup_single_file(outFile); - run_single_file_simple_topology_change(elemFieldName, outFile); - read_and_test_single_file_simple_topology_change(elemFieldName, outFile); - cleanup_single_file(outFile); -} - -} - -