1 // Copyright(C) 1999-2020 National Technology & Engineering Solutions
2 // of Sandia, LLC (NTESS).  Under the terms of Contract DE-NA0003525 with
3 // NTESS, the U.S. Government retains certain rights in this software.
4 //
5 // See packages/seacas/LICENSE for details
6 
7 #ifndef IOSS_Ioss_Region_h
8 #define IOSS_Ioss_Region_h
9 
10 #include "vtk_ioss_mangle.h"
11 
12 #include <Ioss_CoordinateFrame.h> // for CoordinateFrame
13 #include <Ioss_DatabaseIO.h>      // for DatabaseIO
14 #include <Ioss_EntityType.h>      // for EntityType, etc
15 #include <Ioss_GroupingEntity.h>  // for GroupingEntity
16 #include <Ioss_MeshType.h>
17 #include <Ioss_Property.h> // for Property
18 #include <Ioss_State.h>    // for State
19 #include <cstddef>         // for size_t, nullptr
20 #include <cstdint>         // for int64_t
21 #include <functional>      // for less
22 #include <iosfwd>          // for ostream
23 #include <map>             // for map, map<>::value_compare
24 #include <string>          // for string, operator<
25 #include <utility>         // for pair
26 #include <vector>          // for vector
27 namespace Ioss {
28   class Assembly;
29   class Blob;
30   class CommSet;
31   class EdgeBlock;
32   class EdgeSet;
33   class ElementBlock;
34   class ElementSet;
35   class FaceBlock;
36   class FaceSet;
37   class Field;
38   class NodeBlock;
39   class NodeSet;
40   class SideBlock;
41   class SideSet;
42   class StructuredBlock;
43 } // namespace Ioss
44 // Needed for node_global_to_local inline function.
45 
46 namespace Ioss {
47 
48   class CoordinateFrame;
49 
50   using AssemblyContainer = std::vector<Ioss::Assembly *>;
51   using BlobContainer     = std::vector<Ioss::Blob *>;
52 
53   using NodeBlockContainer    = std::vector<NodeBlock *>;
54   using EdgeBlockContainer    = std::vector<EdgeBlock *>;
55   using FaceBlockContainer    = std::vector<FaceBlock *>;
56   using ElementBlockContainer = std::vector<ElementBlock *>;
57 
58   using NodeSetContainer    = std::vector<NodeSet *>;
59   using EdgeSetContainer    = std::vector<EdgeSet *>;
60   using FaceSetContainer    = std::vector<FaceSet *>;
61   using ElementSetContainer = std::vector<ElementSet *>;
62 
63   using SideSetContainer         = std::vector<SideSet *>;
64   using StructuredBlockContainer = std::vector<StructuredBlock *>;
65   using CommSetContainer         = std::vector<CommSet *>;
66   using StateTimeContainer       = std::vector<double>;
67 
68   using CoordinateFrameContainer = std::vector<CoordinateFrame>;
69 
70   using AliasMap = std::map<std::string, std::string, std::less<std::string>>;
71 
72   /** \brief A grouping entity that contains other grouping entities.
73    *
74    * Maintains a list of NodeBlocks, ElementBlocks, NodeLists, CommLists and Surfaces.
75    * [Similar to the "Composite Pattern" in Design Patterns]  All interface to
76    * GroupingEntities is through the Region class; clients of the IO subsystem have no direct
77    * access to the underlying GroupingEntities (other than the Region).
78    */
79   class Region : public GroupingEntity
80   {
81   public:
82     explicit Region(DatabaseIO *iodatabase = nullptr, const std::string &my_name = "");
83 
84     ~Region() override;
85 
type_string()86     std::string type_string() const override { return "Region"; }
short_type_string()87     std::string short_type_string() const override { return "region"; }
contains_string()88     std::string contains_string() const override { return "Entities"; }
type()89     EntityType  type() const override { return REGION; }
90 
91     MeshType          mesh_type() const;
92     const std::string mesh_type_string() const;
93     bool              node_major() const;
94 
95     void output_summary(std::ostream &strm, bool do_transient = true) const;
96 
97     bool supports_field_type(Ioss::EntityType fld_type) const;
98 
99     // Helper function...
100     int64_t node_global_to_local(int64_t global, bool must_exist = true) const;
101 
102     bool begin_mode(State new_state);
103     bool end_mode(State current_state);
104 
105     // Add a new state at this time, return state number
add_state(double time)106     virtual int add_state(double time)
107     {
108       IOSS_FUNC_ENTER(m_);
109       return add_state__(time);
110     }
111     virtual int add_state__(double time);
112 
113     // Get time corresponding to specified state
114 
115     virtual double get_state_time(int state = -1) const;
116     int            get_current_state() const;
117     double         begin_state(int state);
118     double         end_state(int state);
119 
120     /** \brief Determine whether the metadata defining the model (nontransient,
121      *         geometry, and toploloty) has been set.
122      *
123      *  \returns True if the metadata defining the model has been set.
124      */
model_defined()125     bool model_defined() const { return modelDefined; }
126 
127     /** \brief Determine whether the metadata related to the transient
128      *         data has been set.
129      *
130      *  \returns True if the metadata related to the transient data has been set.
131      */
transient_defined()132     bool transient_defined() const { return transientDefined; }
133 
134     // Return a pair consisting of the step (1-based) corresponding to
135     // the maximum time on the database and the corresponding maximum
136     // time value. Note that this may not necessarily be the last step
137     // on the database if cycle and overlay are being used.
138     std::pair<int, double> get_max_time() const;
139 
140     // Return a pair consisting of the step (1-based) corresponding to
141     // the minimum time on the database and the corresponding minimum
142     // time value. Note that this may not necessarily be the first step
143     // on the database if cycle and overlay are being used.
144     std::pair<int, double> get_min_time() const;
145 
146     // Functions for an output region...
147     bool add(NodeBlock *node_block);
148     bool add(EdgeBlock *edge_block);
149     bool add(FaceBlock *face_block);
150     bool add(ElementBlock *element_block);
151     bool add(SideSet *sideset);
152     bool add(NodeSet *nodeset);
153     bool add(EdgeSet *edgeset);
154     bool add(FaceSet *faceset);
155     bool add(ElementSet *elementset);
156     bool add(CommSet *commset);
157     bool add(StructuredBlock *structured_block);
158     bool add(Assembly *assembly);
159     bool add(Blob *blob);
160     bool add(const CoordinateFrame &frame);
161 
162     // Special purpose...
163     bool remove(Assembly *removal);
164 
165     const NodeBlockContainer &      get_node_blocks() const;
166     const EdgeBlockContainer &      get_edge_blocks() const;
167     const FaceBlockContainer &      get_face_blocks() const;
168     const ElementBlockContainer &   get_element_blocks() const;
169     const SideSetContainer &        get_sidesets() const;
170     const NodeSetContainer &        get_nodesets() const;
171     const EdgeSetContainer &        get_edgesets() const;
172     const FaceSetContainer &        get_facesets() const;
173     const ElementSetContainer &     get_elementsets() const;
174     const CommSetContainer &        get_commsets() const;
175     const StructuredBlockContainer &get_structured_blocks() const;
176     const AssemblyContainer &       get_assemblies() const;
177     const BlobContainer &           get_blobs() const;
178     const CoordinateFrameContainer &get_coordinate_frames() const;
179 
180     // Retrieve the Grouping Entity with the specified name.
181     // Returns nullptr if the entity does not exist
182     GroupingEntity * get_entity(const std::string &my_name, EntityType io_type) const;
183     GroupingEntity * get_entity(const std::string &my_name) const;
184     NodeBlock *      get_node_block(const std::string &my_name) const;
185     EdgeBlock *      get_edge_block(const std::string &my_name) const;
186     FaceBlock *      get_face_block(const std::string &my_name) const;
187     ElementBlock *   get_element_block(const std::string &my_name) const;
188     SideSet *        get_sideset(const std::string &my_name) const;
189     SideBlock *      get_sideblock(const std::string &my_name) const;
190     NodeSet *        get_nodeset(const std::string &my_name) const;
191     EdgeSet *        get_edgeset(const std::string &my_name) const;
192     FaceSet *        get_faceset(const std::string &my_name) const;
193     ElementSet *     get_elementset(const std::string &my_name) const;
194     CommSet *        get_commset(const std::string &my_name) const;
195     StructuredBlock *get_structured_block(const std::string &my_name) const;
196     Assembly *       get_assembly(const std::string &my_name) const;
197     Blob *           get_blob(const std::string &my_name) const;
198 
199     // Not guaranteed to be efficient...
200     // Note that not all GroupingEntity's are guaranteed to have an 'id'...
201     GroupingEntity *get_entity(const int64_t id, EntityType io_type) const;
202 
203     const CoordinateFrame &get_coordinate_frame(int64_t id) const;
204 
205     // Add the name 'alias' as an alias for the database entity with the
206     // name 'db_name'. Returns true if alias added; false if problems
207     // adding alias.
208     bool        add_alias(const std::string &db_name, const std::string &alias);
209     bool        add_alias(const GroupingEntity *ge);
210     std::string get_alias(const std::string &alias) const;
211     std::string get_alias__(const std::string &alias) const; // Not locked by mutex
212 
213     const AliasMap &get_alias_map() const;
214 
215     /// Get a map containing all aliases defined for the entity with basename 'name'
216     int get_aliases(const std::string &my_name, std::vector<std::string> &aliases) const;
217 
218     // This routine transfers all relevant aliases from the 'this'
219     // region and applies them to the 'to' file.
220     void transfer_mesh_aliases(Region *to) const;
221 
222     // Ensure that the 'this' region has the same ids and names as the 'from' region.
223     void synchronize_id_and_name(const Region *from, bool sync_attribute_field_names = false);
224 
225     // Returns true if the passed in name refers to a known Entity
226     // defined on this region.  If true, then 'type' (if non-nullptr) is
227     // filled in with the type of the entity; if false, then type (if
228     // non-nullptr) is set to 'INVALID' This function is defined to
229     // consolidate several distinct implementations of this code in
230     // client code. Because of this, the 'type' used in the client
231     // code is repeated here instead of something more generic.
232     bool is_valid_io_entity(const std::string &my_name, unsigned int io_type,
233                             std::string *my_type = nullptr) const;
234 
235     // Retrieve the element block that contains the specified element
236     // The 'local_id' is the local database id (1-based), not the global id.
237     // returns nullptr if no element block contains this element (local_id <= 0
238     // or greater than number of elements in database)
239     ElementBlock *get_element_block(size_t local_id) const;
240 
241     // Retrieve the structured block that contains the specified node
242     // The 'global_offset' is the global offset (0-based)
243     // returns nullptr if no structured block contains this node (local_id <= 0
244     // or greater than number of cell-nodes in database)
245     StructuredBlock *get_structured_block(size_t global_offset) const;
246 
247     // Handle implicit properties -- These are calcuated from data stored
248     // in the grouping entity instead of having an explicit value assigned.
249     // An example would be 'element_block_count' for a region.
250     Property get_implicit_property(const std::string &my_name) const override;
251 
252     const std::vector<std::string> &get_information_records() const;
253     void                            add_information_records(const std::vector<std::string> &info);
254     void                            add_information_record(const std::string &info);
255 
256     const std::vector<std::string> &get_qa_records() const;
257     void add_qa_record(const std::string &code, const std::string &code_qa,
258                        const std::string &date = "", const std::string &time = "");
259 
260   protected:
261     int64_t internal_get_field_data(const Field &field, void *data,
262                                     size_t data_size = 0) const override;
263 
264     int64_t internal_put_field_data(const Field &field, void *data,
265                                     size_t data_size = 0) const override;
266 
267   private:
268     // Add the name 'alias' as an alias for the database entity with the
269     // name 'db_name'. Returns true if alias added; false if problems
270     // adding alias. Not protected by mutex -- call internally only.
271     bool add_alias__(const std::string &db_name, const std::string &alias);
272     bool add_alias__(const GroupingEntity *ge);
273 
274     bool begin_mode__(State new_state);
275     bool end_mode__(State current_state);
276 
277     void delete_database() override;
278 
279     AliasMap aliases_; ///< Stores alias mappings
280 
281     // Containers for all grouping entities
282     NodeBlockContainer    nodeBlocks;
283     EdgeBlockContainer    edgeBlocks;
284     FaceBlockContainer    faceBlocks;
285     ElementBlockContainer elementBlocks;
286 
287     NodeSetContainer    nodeSets;
288     EdgeSetContainer    edgeSets;
289     FaceSetContainer    faceSets;
290     ElementSetContainer elementSets;
291 
292     SideSetContainer           sideSets;
293     CommSetContainer           commSets;
294     CoordinateFrameContainer   coordinateFrames;
295     StructuredBlockContainer   structuredBlocks;
296     AssemblyContainer          assemblies;
297     BlobContainer              blobs;
298     mutable StateTimeContainer stateTimes;
299 
300     int         currentState{-1};
301     mutable int stateCount{0};
302     bool        modelDefined{false};
303     bool        transientDefined{false};
304   };
305 } // namespace Ioss
306 
307 /** \brief Get the index (1-based) of the currently-active state.
308  *
309  *  \returns The index.
310  */
get_current_state()311 inline int Ioss::Region::get_current_state() const { return currentState; }
312 
supports_field_type(Ioss::EntityType fld_type)313 inline bool Ioss::Region::supports_field_type(Ioss::EntityType fld_type) const
314 {
315   return static_cast<unsigned int>((get_database()->entity_field_support() & fld_type) != 0u) != 0u;
316 }
317 
node_global_to_local(int64_t global,bool must_exist)318 inline int64_t Ioss::Region::node_global_to_local(int64_t global, bool must_exist) const
319 {
320   return get_database()->node_global_to_local(global, must_exist);
321 }
322 
323 /** \brief Get all information records (informative strings) for the region's database.
324  *
325  *  \returns The informative strings.
326  */
get_information_records()327 inline const std::vector<std::string> &Ioss::Region::get_information_records() const
328 {
329   IOSS_FUNC_ENTER(m_);
330   return get_database()->get_information_records();
331 }
332 
333 /** \brief Add multiple information records (informative strings) to the region's database.
334  *
335  *  \param[in] info The strings to add.
336  */
add_information_records(const std::vector<std::string> & info)337 inline void Ioss::Region::add_information_records(const std::vector<std::string> &info)
338 {
339   IOSS_FUNC_ENTER(m_);
340   return get_database()->add_information_records(info);
341 }
342 
343 /** \brief Add an information record (an informative string) to the region's database.
344  *
345  *  \param[in] info The string to add.
346  */
add_information_record(const std::string & info)347 inline void Ioss::Region::add_information_record(const std::string &info)
348 {
349   IOSS_FUNC_ENTER(m_);
350   return get_database()->add_information_record(info);
351 }
352 
353 /** \brief Add a QA record, which consists of 4 strings, to the region's database
354  *
355  *  The 4 function parameters correspond to the 4 QA record strings.
356  *
357  *  \param[in] code A descriptive code name, such as the application that modified the database.
358  *  \param[in] code_qa A descriptive string, such as the version of the application that modified
359  * the database.
360  *  \param[in] date A relevant date, such as the date the database was modified.
361  *  \param[in] time A relevant time, such as the time the database was modified.
362  */
add_qa_record(const std::string & code,const std::string & code_qa,const std::string & date,const std::string & time)363 inline void Ioss::Region::add_qa_record(const std::string &code, const std::string &code_qa,
364                                         const std::string &date, const std::string &time)
365 {
366   IOSS_FUNC_ENTER(m_);
367   return get_database()->add_qa_record(code, code_qa, date, time);
368 }
369 
370 /** \brief Get all QA records, each of which consists of 4 strings, from the region's database.
371  *
372  *  The 4 strings that make up a database QA record are:
373  *
374  *  1. A descriptive code name, such as the application that modified the database.
375  *
376  *  2. A descriptive string, such as the version of the application that modified the database.
377  *
378  *  3. A relevant date, such as the date the database was modified.
379  *
380  *  4. A relevant time, such as the time the database was modified.
381  *
382  *  \returns All QA records in a single vector. Every 4 consecutive elements of the
383  *           vector make up a single QA record.
384  */
get_qa_records()385 inline const std::vector<std::string> &Ioss::Region::get_qa_records() const
386 {
387   IOSS_FUNC_ENTER(m_);
388   return get_database()->get_qa_records();
389 }
390 
391 #endif
392