IOSS 2.0

Ioss_Utils.h
Go to the documentation of this file.
1 // Copyright(C) 1999-2017 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 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 //
17 // * Neither the name of NTESS nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 #ifndef IOSS_Ioss_IOUtils_h
34 #define IOSS_Ioss_IOUtils_h
35
36 #include <Ioss_CodeTypes.h>
37 #include <Ioss_Field.h>
38 #include <algorithm> // for sort, lower_bound, copy, etc
39 #include <cassert>
40 #include <cstddef> // for size_t
41 #include <cstdint> // for int64_t
42 #include <cstdlib> // for nullptrr
43 #include <iostream> // for ostringstream, etcstream, etc
44 #include <stdexcept> // for runtime_error
45 #include <string> // for string
46 #include <vector> // for vector
47 namespace Ioss {
48 class Field;
49 } // namespace Ioss
50 namespace Ioss {
51 class GroupingEntity;
52 class Region;
53 class SideBlock;
54 class PropertyManager;
55 struct MeshCopyOptions;
56 } // namespace Ioss
57
58 #if __cplusplus > 199711L
59 #define TOPTR(x) x.data()
60 #else
61 #define TOPTR(x) (x.empty() ? nullptr : &x[0])
62 #endif
63
64 #define IOSS_ERROR(errmsg) throw std::runtime_error(errmsg.str())
65 #define IOSS_WARNING std::cerr
66
67 namespace {
68 // SEE: http://lemire.me/blog/2017/04/10/removing-duplicates-from-lists-quickly
69 template <typename T> size_t unique(std::vector<T> &out, bool skip_first)
70 {
71 if (out.empty())
72 return 0;
73 size_t i = 1;
74 size_t pos = 1;
75 T oldv = out[0];
76 if (skip_first) {
77 i = 2;
78 pos = 2;
79 oldv = out[1];
80 }
81 for (; i < out.size(); ++i) {
82 T newv = out[i];
83 out[pos] = newv;
84 pos += (newv != oldv);
85 oldv = newv;
86 }
87 return pos;
88 }
89 } // namespace
90
91 namespace Ioss {
92
93 /* \brief Utility methods.
94 */
95 class Utils
96 {
97 public:
98 Utils() = default;
99 ~Utils() = default;
100
101 // Assignment operator
102 // Copy constructor
103
104 static void check_dynamic_cast(const void *ptr)
105 {
106 if (ptr == nullptr) {
107 std::cerr << "INTERNAL ERROR: Invalid dynamic cast returned nullptr\n";
108 exit(EXIT_FAILURE);
109 }
110 }
111
112 template <typename T> static void uniquify(std::vector<T> &vec, bool skip_first = false)
113 {
114 auto it = vec.begin();
115 if (skip_first) {
116 it++;
117 }
118 std::sort(it, vec.end());
119 vec.resize(unique(vec, skip_first));
120 vec.shrink_to_fit();
121 }
122
123 template <typename T> static void generate_index(std::vector<T> &index)
124 {
125 T sum = 0;
126 for (size_t i = 0; i < index.size() - 1; i++) {
127 T cnt = index[i];
128 index[i] = sum;
129 sum += cnt;
130 }
131 index.back() = sum;
132 }
133
134 template <typename T> static T find_index_location(T node, const std::vector<T> &index)
135 {
136 // 0-based node numbering
137 // index[p] = first node (0-based) on processor p
138
139 #if 1
140 // Assume data coherence. I.e., a new search will be close to the
141 // previous search.
142 static size_t prev = 1;
143
144 size_t nproc = index.size();
145 if (prev < nproc && index[prev - 1] <= node && index[prev] > node) {
146 return prev - 1;
147 }
148
149 for (size_t p = 1; p < nproc; p++) {
150 if (index[p] > node) {
151 prev = p;
152 return p - 1;
153 }
154 }
155 std::cerr << "FATAL ERROR: find_index_location. Searching for " << node << " in:\n";
156 for (auto idx : index) {
157 std::cerr << idx << ", ";
158 }
159 std::cerr << "\n";
160 assert(1 == 0); // Cannot happen...
161 return 0;
162 #else
163 return std::distance(index.begin(), std::upper_bound(index.begin(), index.end(), node)) - 1;
164 #endif
165 }
166
167 template <typename T> static void clear(std::vector<T> &vec)
168 {
169 vec.clear();
170 vec.shrink_to_fit();
171 assert(vec.capacity() == 0);
172 }
173
174 inline static int power_2(int count)
175 {
176 // Return the power of two which is equal to or greater than 'count'
177 // count = 15 -> returns 16
178 // count = 16 -> returns 16
179 // count = 17 -> returns 32
180
181 // Use brute force...
182 int pow2 = 1;
183 while (pow2 < count) {
184 pow2 *= 2;
185 }
186 return pow2;
187 }
188
189 template <typename T> static bool check_block_order(const std::vector<T *> &blocks)
190 {
191 #ifndef NDEBUG
192 // Verify that element blocks are defined in sorted offset order...
193 typename std::vector<T *>::const_iterator I;
194
195 int64_t eb_offset = -1;
196 for (I = blocks.begin(); I != blocks.end(); ++I) {
197 int64_t this_off = (*I)->get_offset();
198 if (this_off < eb_offset) {
199 {
200 {
201 return false;
202 }
203 }
204 }
205 eb_offset = this_off;
206 }
207 #endif
208 return true;
209 }
210
211 static int log_power_2(uint64_t value);
212
213 static char **get_name_array(size_t count, int size);
214 static void delete_name_array(char **names, int count);
215
216 // Fill time_string and date_string with current time and date
217 // formatted as "HH:MM:SS" for time and "yy/mm/dd" or "yyyy/mm/dd"
218 // for date
219 static void time_and_date(char *time_string, char *date_string, size_t length);
220
221 static std::string decode_filename(const std::string &filename, int processor,
222 int num_processors);
223 static size_t get_number(const std::string &suffix);
224 static int64_t extract_id(const std::string &name_id);
225 static std::string encode_entity_name(const std::string &entity_type, int64_t id);
226
227 // Convert 'name' to lowercase and convert spaces to '_'
228 static void fixup_name(char *name);
229 static void fixup_name(std::string &name);
230
231 // Check whether property 'prop_name' exists and if so, set 'prop_value'
232 // based on the property value. Either "TRUE", "YES", "ON", or 1 for true;
233 // or "FALSE", "NO", "OFF", or not equal to 1 for false.
234 // Returns true/false depending on whether property found and value set.
235 // Does not set 'prop_val' if 'prop_name' does not exist.
236 static bool check_set_bool_property(const Ioss::PropertyManager &properties,
237 const std::string &prop_name, bool &prop_value);
238
239 // Returns true if the property "omitted" exists on "block"
240 static bool block_is_omitted(Ioss::GroupingEntity *block);
241
242 // Process the base element type 'base' which has
243 // 'nodes_per_element' nodes and a spatial dimension of 'spatial'
244 // into a form that the IO system can (hopefully) recognize.
245 // Lowercases the name; converts spaces to '_', adds
246 // nodes_per_element at end of name (if not already there), and
247 // does some other transformations to remove some exodusII ambiguity.
248 static std::string fixup_type(const std::string &base, int nodes_per_element, int spatial);
249
250 static std::string uppercase(std::string name);
251 static std::string lowercase(std::string name);
252
253 static void check_non_null(void *ptr, const char *type, const std::string &name,
254 const std::string &func);
255
256 static int case_strcmp(const std::string &s1, const std::string &s2);
257
258 // Return a string containing information about the current :
259 // computing platform. This is used as information data in the
260 // created results file to help in tracking when/where/... the file
261 // was created.
262 static std::string platform_information();
263
264 // Return amount of memory being used on this processor
265 static size_t get_memory_info();
266 static size_t get_hwm_memory_info();
267
268 static void abort();
269
270 // Return a filename relative to the specified working directory (if any)
271 // of the current execution. Working_directory must end with '/' or be empty.
272 static std::string local_filename(const std::string &relative_filename, const std::string &type,
273 const std::string &working_directory);
274
275 static void get_fields(int64_t entity_count, char **names, size_t num_names,
276 Ioss::Field::RoleType fld_role, bool enable_field_recognition,
277 char suffix_separator, int *local_truth,
278 std::vector<Ioss::Field> &fields);
279
280 static int field_warning(const Ioss::GroupingEntity *ge, const Ioss::Field &field,
281 const std::string &inout);
282
283 static void calculate_sideblock_membership(IntVector &face_is_member, const SideBlock *ef_blk,
284 size_t int_byte_size, const void *element,
285 const void *sides, int64_t number_sides,
286 const Region *region);
287
288 // And yet another idiosyncrasy of sidesets...
289 // The side of an element (especially shells) can be
290 // either a face or an edge in the same sideset. The
291 // ordinal of an edge is (local_edge_number+#faces) on the
292 // database, but needs to be (local_edge_number) for
293 // Sierra...
294 //
295 // If the sideblock has a "parent_element_topology" and a
296 // "topology", then we can determine whether to offset the
297 // side ordinals...
298 static int64_t get_side_offset(const Ioss::SideBlock *sb);
299
300 static unsigned int hash(const std::string &name);
301
302 static double timer();
303
304 // Return a vector of strings containing the lines of the input file.
305 // Should only be called by a single processor or each processor will
306 // be accessing the file at the same time...
307 static void input_file(const std::string &file_name, std::vector<std::string> *lines,
308 size_t max_line_length = 0);
309
310 template <class T> static std::string to_string(const T &t) { return std::to_string(t); }
311
312 // Many databases have a maximum length for variable names which can
313 // cause a problem with variable name length.
314 //
315 // This routine tries to shorten long variable names to an acceptable
316 // length ('max_var_len' characters max). If the name is already less than this
317 // length, it is returned unchanged...
318 //
319 // Since there is a (good) chance that two shortened names will match,
320 // a 2-letter 'hash' code is appended to the end of the variable name.
321 //
322 // So, we shorten the name to a maximum of 'max_var_len'-3 characters and append a
323 // 2 character hash+separator.
324 //
325 // It also converts name to lowercase and converts spaces to '_'
326 static std::string variable_name_kluge(const std::string &name, size_t component_count,
327 size_t copies, size_t max_var_len);
328
329 // The model for a history file is a single sphere element (1 node, 1 element)
330 // This is needed for some applications that read this file that require a "mesh"
331 // even though a history file is just a collection of global variables with no
332 // real mesh. This routine will add the mesh portion to a history file.
333 static void generate_history_mesh(Ioss::Region *region);
334
335 // Copy the mesh in 'region' to 'output_region'. Behavior can be controlled
336 // via options in 'options'
337 static void copy_database(Ioss::Region &region, Ioss::Region &output_region,
338 Ioss::MeshCopyOptions &options);
339 };
340 } // namespace Ioss
341 #endif
Ioss_CodeTypes.h
Ioss::Utils::power_2
static int power_2(int count)
Definition: Ioss_Utils.h:174
Ioex::extract_id
int64_t extract_id(const std::string &name_id)
Definition: Ioex_Utils.C:300
Ioss
The main namespace for the Ioss library.
Definition: Iocgns_DatabaseIO.h:50
Ioss::Utils::check_dynamic_cast
static void check_dynamic_cast(const void *ptr)
Definition: Ioss_Utils.h:104
Ioss::Utils
Definition: Ioss_Utils.h:95
Ioss::GroupingEntity
Base class for all &#39;grouping&#39; entities. The following derived classes are typical: ...
Definition: Ioss_GroupingEntity.h:93
Ioss::Field::RoleType
RoleType
Definition: Ioss_Field.h:75
Ioss::MeshCopyOptions
Definition: Ioss_MeshCopyOptions.h:35
Iovs::field_warning
int field_warning(const Ioss::GroupingEntity *ge, const Ioss::Field &field, const std::string &inout)
Definition: Iovs_DatabaseIO.C:973
Ioss::SideBlock
A collection of element sides having the same topology.
Definition: Ioss_SideBlock.h:61
Ioss::IntVector
std::vector< int > IntVector
Definition: Ioss_CodeTypes.h:42
anonymous_namespace{Ioss_Utils.h}::unique
size_t unique(std::vector< T > &out, bool skip_first)
Definition: Ioss_Utils.h:69
Ioss::Utils::to_string
static std::string to_string(const T &t)
Definition: Ioss_Utils.h:310
Ioss::Utils::find_index_location
static T find_index_location(T node, const std::vector< T > &index)
Definition: Ioss_Utils.h:134
anonymous_namespace{Iofx_DatabaseIO.C}::max_line_length
const size_t max_line_length
Definition: Iofx_DatabaseIO.C:96
Ioss_Field.h
Ioss::Region
A grouping entity that contains other grouping entities.
Definition: Ioss_Region.h:98
anonymous_namespace{io_info.C}::name
std::string name(Ioss::GroupingEntity *entity)
Definition: io_info.C:71
Ioss::Utils::check_block_order
static bool check_block_order(const std::vector< T *> &blocks)
Definition: Ioss_Utils.h:189
anonymous_namespace{Ioss_Region.C}::uppercase
std::string uppercase(const std::string &my_name)
Definition: Ioss_Region.C:2285
Ioss::Field
Holds metadata for bulk data associated with a GroupingEntity.
Definition: Ioss_Field.h:47
Ioss::Utils::uniquify
static void uniquify(std::vector< T > &vec, bool skip_first=false)
Definition: Ioss_Utils.h:112
Ioss::PropertyManager
A collection of Ioss::Property objects.
Definition: Ioss_PropertyManager.h:49
anonymous_namespace{Iovs_DatabaseIO.C}::entity_type
entity_type
Definition: Iovs_DatabaseIO.C:81
Ioss::Utils::generate_index
static void generate_index(std::vector< T > &index)
Definition: Ioss_Utils.h:123
Ioss::Utils::clear
static void clear(std::vector< T > &vec)
Definition: Ioss_Utils.h:167