// Copyright(C) 1999-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 #pragma once #include "vtk_ioss_mangle.h" #include // for CoordinateFrame #include // for DatabaseIO #include // for EntityType, etc #include // for GroupingEntity #include #include // for Property #include // for State #include // for size_t, nullptr #include // for int64_t #include // for less #include // for ostream #include // for map, map<>::value_compare #include // for string, operator< #include // for pair #include // for vector namespace Ioss { class Assembly; class Blob; class CommSet; class EdgeBlock; class EdgeSet; class ElementBlock; class ElementSet; class FaceBlock; class FaceSet; class Field; class NodeBlock; class NodeSet; class SideBlock; class SideSet; class StructuredBlock; } // namespace Ioss // Needed for node_global_to_local inline function. namespace Ioss { class CoordinateFrame; using AssemblyContainer = std::vector; using BlobContainer = std::vector; using NodeBlockContainer = std::vector; using EdgeBlockContainer = std::vector; using FaceBlockContainer = std::vector; using ElementBlockContainer = std::vector; using NodeSetContainer = std::vector; using EdgeSetContainer = std::vector; using FaceSetContainer = std::vector; using ElementSetContainer = std::vector; using SideSetContainer = std::vector; using StructuredBlockContainer = std::vector; using CommSetContainer = std::vector; using StateTimeContainer = std::vector; using CoordinateFrameContainer = std::vector; using AliasMap = std::map>; /** \brief A grouping entity that contains other grouping entities. * * Maintains a list of NodeBlocks, ElementBlocks, NodeLists, CommLists and Surfaces. * [Similar to the "Composite Pattern" in Design Patterns] All interface to * GroupingEntities is through the Region class; clients of the IO subsystem have no direct * access to the underlying GroupingEntities (other than the Region). */ class Region : public GroupingEntity { public: explicit Region(DatabaseIO *iodatabase = nullptr, const std::string &my_name = ""); ~Region() override; std::string type_string() const override { return "Region"; } std::string short_type_string() const override { return "region"; } std::string contains_string() const override { return "Entities"; } EntityType type() const override { return REGION; } MeshType mesh_type() const; const std::string mesh_type_string() const; bool node_major() const; void output_summary(std::ostream &strm, bool do_transient = true) const; bool supports_field_type(Ioss::EntityType fld_type) const; // Helper function... int64_t node_global_to_local(int64_t global, bool must_exist = true) const; bool begin_mode(State new_state); bool end_mode(State current_state); // Add a new state at this time, return state number virtual int add_state(double time) { IOSS_FUNC_ENTER(m_); return add_state__(time); } virtual int add_state__(double time); // Get time corresponding to specified state virtual double get_state_time(int state = -1) const; int get_current_state() const; double begin_state(int state); double end_state(int state); /** \brief Determine whether the metadata defining the model (nontransient, * geometry, and toploloty) has been set. * * \returns True if the metadata defining the model has been set. */ bool model_defined() const { return modelDefined; } /** \brief Determine whether the metadata related to the transient * data has been set. * * \returns True if the metadata related to the transient data has been set. */ bool transient_defined() const { return transientDefined; } // Return a pair consisting of the step (1-based) corresponding to // the maximum time on the database and the corresponding maximum // time value. Note that this may not necessarily be the last step // on the database if cycle and overlay are being used. std::pair get_max_time() const; // Return a pair consisting of the step (1-based) corresponding to // the minimum time on the database and the corresponding minimum // time value. Note that this may not necessarily be the first step // on the database if cycle and overlay are being used. std::pair get_min_time() const; // Functions for an output region... bool add(NodeBlock *node_block); bool add(EdgeBlock *edge_block); bool add(FaceBlock *face_block); bool add(ElementBlock *element_block); bool add(SideSet *sideset); bool add(NodeSet *nodeset); bool add(EdgeSet *edgeset); bool add(FaceSet *faceset); bool add(ElementSet *elementset); bool add(CommSet *commset); bool add(StructuredBlock *structured_block); bool add(Assembly *assembly); bool add(Blob *blob); bool add(const CoordinateFrame &frame); // Special purpose... bool remove(Assembly *removal); const NodeBlockContainer &get_node_blocks() const; const EdgeBlockContainer &get_edge_blocks() const; const FaceBlockContainer &get_face_blocks() const; const ElementBlockContainer &get_element_blocks() const; const SideSetContainer &get_sidesets() const; const NodeSetContainer &get_nodesets() const; const EdgeSetContainer &get_edgesets() const; const FaceSetContainer &get_facesets() const; const ElementSetContainer &get_elementsets() const; const CommSetContainer &get_commsets() const; const StructuredBlockContainer &get_structured_blocks() const; const AssemblyContainer &get_assemblies() const; const BlobContainer &get_blobs() const; const CoordinateFrameContainer &get_coordinate_frames() const; // Retrieve the Grouping Entity with the specified name. // Returns nullptr if the entity does not exist GroupingEntity *get_entity(const std::string &my_name, EntityType io_type) const; GroupingEntity *get_entity(const std::string &my_name) const; NodeBlock *get_node_block(const std::string &my_name) const; EdgeBlock *get_edge_block(const std::string &my_name) const; FaceBlock *get_face_block(const std::string &my_name) const; ElementBlock *get_element_block(const std::string &my_name) const; SideSet *get_sideset(const std::string &my_name) const; SideBlock *get_sideblock(const std::string &my_name) const; NodeSet *get_nodeset(const std::string &my_name) const; EdgeSet *get_edgeset(const std::string &my_name) const; FaceSet *get_faceset(const std::string &my_name) const; ElementSet *get_elementset(const std::string &my_name) const; CommSet *get_commset(const std::string &my_name) const; StructuredBlock *get_structured_block(const std::string &my_name) const; Assembly *get_assembly(const std::string &my_name) const; Blob *get_blob(const std::string &my_name) const; // Not guaranteed to be efficient... // Note that not all GroupingEntity's are guaranteed to have an 'id'... GroupingEntity *get_entity(const int64_t id, EntityType io_type) const; const CoordinateFrame &get_coordinate_frame(int64_t id) const; // Add the name 'alias' as an alias for the database entity of // type 'type' with the name 'db_name'. Returns true if alias // added; false if problems adding alias. bool add_alias(const std::string &db_name, const std::string &alias, EntityType type); bool add_alias(const std::string &db_name, const std::string &alias); bool add_alias(const GroupingEntity *ge); std::string get_alias(const std::string &alias, EntityType type) const; std::string get_alias__(const std::string &alias, EntityType type) const; // Not locked by mutex const AliasMap &get_alias_map(EntityType entity_type) const; /// Get a map containing all aliases defined for the entity with basename 'my_name' int get_aliases(const std::string &my_name, EntityType type, std::vector &aliases) const; // This routine transfers all relevant aliases from the 'this' // region and applies them to the 'to' file. void transfer_mesh_aliases(Region *to) const; // Ensure that the 'this' region has the same ids and names as the 'from' region. void synchronize_id_and_name(const Region *from, bool sync_attribute_field_names = false); // Returns true if the passed in name refers to a known Entity // defined on this region. If true, then 'type' (if non-nullptr) is // filled in with the type of the entity; if false, then type (if // non-nullptr) is set to 'INVALID' This function is defined to // consolidate several distinct implementations of this code in // client code. Because of this, the 'type' used in the client // code is repeated here instead of something more generic. bool is_valid_io_entity(const std::string &my_name, unsigned int io_type, std::string *my_type = nullptr) const; void check_for_duplicate_names(const Ioss::GroupingEntity *entity) const; // Retrieve the element block that contains the specified element // The 'local_id' is the local database id (1-based), not the global id. // returns nullptr if no element block contains this element (local_id <= 0 // or greater than number of elements in database) ElementBlock *get_element_block(size_t local_id) const; // Retrieve the structured block that contains the specified node // The 'global_offset' is the global offset (0-based) // returns nullptr if no structured block contains this node (local_id <= 0 // or greater than number of cell-nodes in database) StructuredBlock *get_structured_block(size_t global_offset) const; // Handle implicit properties -- These are calcuated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; const std::vector &get_information_records() const; void add_information_records(const std::vector &info); void add_information_record(const std::string &info); const std::vector &get_qa_records() const; void add_qa_record(const std::string &code, const std::string &code_qa, const std::string &date = "", const std::string &time = ""); protected: int64_t internal_get_field_data(const Field &field, void *data, size_t data_size = 0) const override; int64_t internal_put_field_data(const Field &field, void *data, size_t data_size = 0) const override; private: // Add the name 'alias' as an alias for the database entity with the // name 'db_name'. Returns true if alias added; false if problems // adding alias. Not protected by mutex -- call internally only. bool add_alias__(const std::string &db_name, const std::string &alias, EntityType type); bool add_alias__(const GroupingEntity *ge); bool begin_mode__(State new_state); bool end_mode__(State current_state); void delete_database() override; mutable std::map aliases_; ///< Stores alias mappings // Containers for all grouping entities NodeBlockContainer nodeBlocks; EdgeBlockContainer edgeBlocks; FaceBlockContainer faceBlocks; ElementBlockContainer elementBlocks; NodeSetContainer nodeSets; EdgeSetContainer edgeSets; FaceSetContainer faceSets; ElementSetContainer elementSets; SideSetContainer sideSets; CommSetContainer commSets; CoordinateFrameContainer coordinateFrames; StructuredBlockContainer structuredBlocks; AssemblyContainer assemblies; BlobContainer blobs; mutable StateTimeContainer stateTimes; int currentState{-1}; mutable int stateCount{0}; bool modelDefined{false}; bool transientDefined{false}; }; } // namespace Ioss /** \brief Get the index (1-based) of the currently-active state. * * \returns The index. */ inline int Ioss::Region::get_current_state() const { return currentState; } inline bool Ioss::Region::supports_field_type(Ioss::EntityType fld_type) const { return static_cast((get_database()->entity_field_support() & fld_type) != 0u) != 0u; } inline int64_t Ioss::Region::node_global_to_local(int64_t global, bool must_exist) const { return get_database()->node_global_to_local(global, must_exist); } /** \brief Get all information records (informative strings) for the region's database. * * \returns The informative strings. */ inline const std::vector &Ioss::Region::get_information_records() const { IOSS_FUNC_ENTER(m_); return get_database()->get_information_records(); } /** \brief Add multiple information records (informative strings) to the region's database. * * \param[in] info The strings to add. */ inline void Ioss::Region::add_information_records(const std::vector &info) { IOSS_FUNC_ENTER(m_); return get_database()->add_information_records(info); } /** \brief Add an information record (an informative string) to the region's database. * * \param[in] info The string to add. */ inline void Ioss::Region::add_information_record(const std::string &info) { IOSS_FUNC_ENTER(m_); return get_database()->add_information_record(info); } /** \brief Add a QA record, which consists of 4 strings, to the region's database * * The 4 function parameters correspond to the 4 QA record strings. * * \param[in] code A descriptive code name, such as the application that modified the database. * \param[in] code_qa A descriptive string, such as the version of the application that modified * the database. * \param[in] date A relevant date, such as the date the database was modified. * \param[in] time A relevant time, such as the time the database was modified. */ inline void Ioss::Region::add_qa_record(const std::string &code, const std::string &code_qa, const std::string &date, const std::string &time) { IOSS_FUNC_ENTER(m_); return get_database()->add_qa_record(code, code_qa, date, time); } /** \brief Get all QA records, each of which consists of 4 strings, from the region's database. * * The 4 strings that make up a database QA record are: * * 1. A descriptive code name, such as the application that modified the database. * * 2. A descriptive string, such as the version of the application that modified the database. * * 3. A relevant date, such as the date the database was modified. * * 4. A relevant time, such as the time the database was modified. * * \returns All QA records in a single vector. Every 4 consecutive elements of the * vector make up a single QA record. */ inline const std::vector &Ioss::Region::get_qa_records() const { IOSS_FUNC_ENTER(m_); return get_database()->get_qa_records(); }