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_Utils_h
34 #define IOSS_Ioss_Utils_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 <cmath>
41 #include <cstddef> // for size_t
42 #include <cstdint> // for int64_t
43 #include <cstdlib> // for nullptrr
44 #include <iostream> // for ostringstream, etcstream, etc
45 #include <stdexcept> // for runtime_error
46 #include <string> // for string
47 #include <vector> // for vector
48 namespace Ioss {
49  class Field;
50 } // namespace Ioss
51 namespace Ioss {
52  class GroupingEntity;
53  class Region;
54  class SideBlock;
55  class PropertyManager;
56  struct MeshCopyOptions;
57 } // namespace Ioss
58 
59 #if __cplusplus > 199711L
60 #define TOPTR(x) x.data()
61 #else
62 #define TOPTR(x) (x.empty() ? nullptr : &x[0])
63 #endif
64 
65 #define IOSS_ERROR(errmsg) throw std::runtime_error(errmsg.str())
66 #define IOSS_WARNING std::cerr
67 
68 namespace {
69  // SEE: http://lemire.me/blog/2017/04/10/removing-duplicates-from-lists-quickly
70  template <typename T> size_t unique(std::vector<T> &out, bool skip_first)
71  {
72  if (out.empty())
73  return 0;
74  size_t i = 1;
75  size_t pos = 1;
76  T oldv = out[0];
77  if (skip_first) {
78  i = 2;
79  pos = 2;
80  oldv = out[1];
81  }
82  for (; i < out.size(); ++i) {
83  T newv = out[i];
84  out[pos] = newv;
85  pos += (newv != oldv);
86  oldv = newv;
87  }
88  return pos;
89  }
90 } // namespace
91 
92 namespace Ioss {
93 
94  /* \brief Utility methods.
95  */
96  class Utils
97  {
98  public:
99  Utils() = default;
100  ~Utils() = default;
101 
102  // Assignment operator
103  // Copy constructor
104 
105  static void check_dynamic_cast(const void *ptr)
106  {
107  if (ptr == nullptr) {
108  std::cerr << "INTERNAL ERROR: Invalid dynamic cast returned nullptr\n";
109  exit(EXIT_FAILURE);
110  }
111  }
112 
113  template <typename T> static void uniquify(std::vector<T> &vec, bool skip_first = false)
114  {
115  auto it = vec.begin();
116  if (skip_first) {
117  it++;
118  }
119  std::sort(it, vec.end());
120  vec.resize(unique(vec, skip_first));
121  vec.shrink_to_fit();
122  }
123 
124  template <typename T> static void generate_index(std::vector<T> &index)
125  {
126  T sum = 0;
127  for (size_t i = 0; i < index.size() - 1; i++) {
128  T cnt = index[i];
129  index[i] = sum;
130  sum += cnt;
131  }
132  index.back() = sum;
133  }
134 
135  template <typename T> static T find_index_location(T node, const std::vector<T> &index)
136  {
137  // 0-based node numbering
138  // index[p] = first node (0-based) on processor p
139 
140 #if 1
141  // Assume data coherence. I.e., a new search will be close to the
142  // previous search.
143  static size_t prev = 1;
144 
145  size_t nproc = index.size();
146  if (prev < nproc && index[prev - 1] <= node && index[prev] > node) {
147  return prev - 1;
148  }
149 
150  for (size_t p = 1; p < nproc; p++) {
151  if (index[p] > node) {
152  prev = p;
153  return p - 1;
154  }
155  }
156  std::cerr << "FATAL ERROR: find_index_location. Searching for " << node << " in:\n";
157  for (auto idx : index) {
158  std::cerr << idx << ", ";
159  }
160  std::cerr << "\n";
161  assert(1 == 0); // Cannot happen...
162  return 0;
163 #else
164  return std::distance(index.begin(), std::upper_bound(index.begin(), index.end(), node)) - 1;
165 #endif
166  }
167 
168  static void copy_string(char *dest, char const *source, size_t elements);
169 
170  static void copy_string(char *dest, const std::string &source, size_t elements)
171  {
172  copy_string(dest, source.c_str(), elements);
173  }
174 
175  template <size_t size> static void copy_string(char (&output)[size], const std::string &source)
176  {
177  copy_string(output, source.c_str(), size);
178  }
179 
180  template <size_t size> static void copy_string(char (&output)[size], const char *source)
181  {
182  // Copy the string — don’t copy too many bytes.
183  copy_string(output, source, size);
184  }
185 
186  template <typename T> static void clear(std::vector<T> &vec)
187  {
188  vec.clear();
189  vec.shrink_to_fit();
190  assert(vec.capacity() == 0);
191  }
192 
193  /**
194  * Returns the number of digits required to print the number.
195  * If `use_commas` is specified, then the width will be adjusted
196  * to account for the comma used every 3 digits.
197  * (1,234,567,890 would return 13)
198  * Typically used with the `fmt::print()` functions as:
199  * `fmt::print("{:{}n}", number, number_width(number,true))`
200  * `fmt::print("{:{}d}", number, number_width(number,false))`
201  */
202  inline static int number_width(const size_t number, bool use_commas = false)
203  {
204  if (number == 0) {
205  return 1;
206  }
207  int width = std::floor(std::log10(number)) + 1;
208  if (use_commas) {
209  width += (width / 3);
210  }
211  return width;
212  }
213 
214  inline static int power_2(int count)
215  {
216  // Return the power of two which is equal to or greater than 'count'
217  // count = 15 -> returns 16
218  // count = 16 -> returns 16
219  // count = 17 -> returns 32
220 
221  // Use brute force...
222  int pow2 = 1;
223  while (pow2 < count) {
224  pow2 *= 2;
225  }
226  return pow2;
227  }
228 
229  template <typename T> static bool check_block_order(const std::vector<T *> &blocks)
230  {
231 #ifndef NDEBUG
232  // Verify that element blocks are defined in sorted offset order...
233  typename std::vector<T *>::const_iterator I;
234 
235  int64_t eb_offset = -1;
236  for (I = blocks.begin(); I != blocks.end(); ++I) {
237  int64_t this_off = (*I)->get_offset();
238  if (this_off < eb_offset) {
239  {
240  {
241  return false;
242  }
243  }
244  }
245  eb_offset = this_off;
246  }
247 #endif
248  return true;
249  }
250 
251  static int log_power_2(uint64_t value);
252 
253  static char **get_name_array(size_t count, int size);
254  static void delete_name_array(char **names, int count);
255 
256  // Fill time_string and date_string with current time and date
257  // formatted as "HH:MM:SS" for time and "yy/mm/dd" or "yyyy/mm/dd"
258  // for date
259  static void time_and_date(char *time_string, char *date_string, size_t length);
260 
261  static std::string decode_filename(const std::string &filename, int processor,
262  int num_processors);
263  static size_t get_number(const std::string &suffix);
264  static int64_t extract_id(const std::string &name_id);
265  static std::string encode_entity_name(const std::string &entity_type, int64_t id);
266 
267  // Convert 'name' to lowercase and convert spaces to '_'
268  static void fixup_name(char *name);
269  static void fixup_name(std::string &name);
270 
271  // Check whether property 'prop_name' exists and if so, set 'prop_value'
272  // based on the property value. Either "TRUE", "YES", "ON", or 1 for true;
273  // or "FALSE", "NO", "OFF", or not equal to 1 for false.
274  // Returns true/false depending on whether property found and value set.
275  // Does not set 'prop_val' if 'prop_name' does not exist.
276  static bool check_set_bool_property(const Ioss::PropertyManager &properties,
277  const std::string &prop_name, bool &prop_value);
278 
279  // Returns true if the property "omitted" exists on "block"
280  static bool block_is_omitted(Ioss::GroupingEntity *block);
281 
282  // Process the base element type 'base' which has
283  // 'nodes_per_element' nodes and a spatial dimension of 'spatial'
284  // into a form that the IO system can (hopefully) recognize.
285  // Lowercases the name; converts spaces to '_', adds
286  // nodes_per_element at end of name (if not already there), and
287  // does some other transformations to remove some exodusII ambiguity.
288  static std::string fixup_type(const std::string &base, int nodes_per_element, int spatial);
289 
290  static std::string uppercase(std::string name);
291  static std::string lowercase(std::string name);
292 
293  static void check_non_null(void *ptr, const char *type, const std::string &name,
294  const std::string &func);
295 
296  static int case_strcmp(const std::string &s1, const std::string &s2);
297 
298  // Return a string containing information about the current :
299  // computing platform. This is used as information data in the
300  // created results file to help in tracking when/where/... the file
301  // was created.
302  static std::string platform_information();
303 
304  // Return amount of memory being used on this processor
305  static size_t get_memory_info();
306  static size_t get_hwm_memory_info();
307 
308  // Return a filename relative to the specified working directory (if any)
309  // of the current execution. Working_directory must end with '/' or be empty.
310  static std::string local_filename(const std::string &relative_filename, const std::string &type,
311  const std::string &working_directory);
312 
313  static void get_fields(int64_t entity_count, char **names, size_t num_names,
314  Ioss::Field::RoleType fld_role, bool enable_field_recognition,
315  char suffix_separator, int *local_truth,
316  std::vector<Ioss::Field> &fields);
317 
318  static int field_warning(const Ioss::GroupingEntity *ge, const Ioss::Field &field,
319  const std::string &inout);
320 
321  static void calculate_sideblock_membership(IntVector &face_is_member, const SideBlock *ef_blk,
322  size_t int_byte_size, const void *element,
323  const void *sides, int64_t number_sides,
324  const Region *region);
325 
326  // And yet another idiosyncrasy of sidesets...
327  // The side of an element (especially shells) can be
328  // either a face or an edge in the same sideset. The
329  // ordinal of an edge is (local_edge_number+#faces) on the
330  // database, but needs to be (local_edge_number) for
331  // Sierra...
332  //
333  // If the sideblock has a "parent_element_topology" and a
334  // "topology", then we can determine whether to offset the
335  // side ordinals...
336  static int64_t get_side_offset(const Ioss::SideBlock *sb);
337 
338  static unsigned int hash(const std::string &name);
339 
340  static double timer();
341 
342  // Return a vector of strings containing the lines of the input file.
343  // Should only be called by a single processor or each processor will
344  // be accessing the file at the same time...
345  static void input_file(const std::string &file_name, std::vector<std::string> *lines,
346  size_t max_line_length = 0);
347 
348  template <class T> static std::string to_string(const T &t) { return std::to_string(t); }
349 
350  // Many databases have a maximum length for variable names which can
351  // cause a problem with variable name length.
352  //
353  // This routine tries to shorten long variable names to an acceptable
354  // length ('max_var_len' characters max). If the name is already less than this
355  // length, it is returned unchanged...
356  //
357  // Since there is a (good) chance that two shortened names will match,
358  // a 2-letter 'hash' code is appended to the end of the variable name.
359  //
360  // So, we shorten the name to a maximum of 'max_var_len'-3 characters and append a
361  // 2 character hash+separator.
362  //
363  // It also converts name to lowercase and converts spaces to '_'
364  static std::string variable_name_kluge(const std::string &name, size_t component_count,
365  size_t copies, size_t max_var_len);
366 
367  // The model for a history file is a single sphere element (1 node, 1 element)
368  // This is needed for some applications that read this file that require a "mesh"
369  // even though a history file is just a collection of global variables with no
370  // real mesh. This routine will add the mesh portion to a history file.
371  static void generate_history_mesh(Ioss::Region *region);
372 
373  // Copy the mesh in 'region' to 'output_region'. Behavior can be controlled
374  // via options in 'options'
375  static void copy_database(Ioss::Region &region, Ioss::Region &output_region,
376  Ioss::MeshCopyOptions &options);
377  };
378 } // namespace Ioss
379 #endif
Utils()=default
static int number_width(const size_t number, bool use_commas=false)
Definition: Ioss_Utils.h:202
static std::string uppercase(std::string name)
Convert a string to upper case.
Definition: Ioss_Utils.C:1198
static int power_2(int count)
Definition: Ioss_Utils.h:214
static size_t get_memory_info()
Return amount of memory being used on this processor.
Definition: Ioss_Utils.C:873
The main namespace for the Ioss library.
Definition: Ioad_DatabaseIO.C:66
static void check_dynamic_cast(const void *ptr)
Definition: Ioss_Utils.h:105
~Utils()=default
Definition: Ioss_Utils.h:96
Base class for all 'grouping' entities. The following derived classes are typical:
Definition: Ioss_GroupingEntity.h:93
RoleType
Definition: Ioss_Field.h:75
Definition: Ioss_MeshCopyOptions.h:35
static std::string encode_entity_name(const std::string &entity_type, int64_t id)
Definition: Ioss_Utils.C:309
static void input_file(const std::string &file_name, std::vector< std::string > *lines, size_t max_line_length=0)
Convert an input file to a vector of strings containing one string for each line of the file.
Definition: Ioss_Utils.C:1139
static bool check_set_bool_property(const Ioss::PropertyManager &properties, const std::string &prop_name, bool &prop_value)
Check whether property 'prop_name' exists and if so, set 'prop_value'.
Definition: Ioss_Utils.C:1226
static void copy_string(char(&output)[size], const char *source)
Definition: Ioss_Utils.h:180
A collection of element sides having the same topology.
Definition: Ioss_SideBlock.h:61
std::vector< int > IntVector
Definition: Ioss_CodeTypes.h:43
static bool block_is_omitted(Ioss::GroupingEntity *block)
Determine whether an entity has the property "omitted.".
Definition: Ioss_Utils.C:967
static std::string variable_name_kluge(const std::string &name, size_t component_count, size_t copies, size_t max_var_len)
Tries to shorten long variable names to an acceptable length, and converts to lowercase and spaces to...
Definition: Ioss_Utils.C:1350
static int64_t get_side_offset(const Ioss::SideBlock *sb)
Get the appropriate index offset for the sides of elements in a SideBlock.
Definition: Ioss_Utils.C:1080
static int case_strcmp(const std::string &s1, const std::string &s2)
Case-insensitive string comparison.
Definition: Ioss_Utils.C:1179
static std::string lowercase(std::string name)
Convert a string to lower case.
Definition: Ioss_Utils.C:1209
static unsigned int hash(const std::string &name)
Definition: Ioss_Utils.C:1098
static void copy_string(char *dest, const std::string &source, size_t elements)
Definition: Ioss_Utils.h:170
size_t unique(std::vector< T > &out, bool skip_first)
Definition: Ioss_Utils.h:70
static std::string to_string(const T &t)
Definition: Ioss_Utils.h:348
static void fixup_name(char *name)
Convert a string to lower case, and convert spaces to '_'.
Definition: Ioss_Utils.C:1263
static void get_fields(int64_t entity_count, char **names, size_t num_names, Ioss::Field::RoleType fld_role, bool enable_field_recognition, char suffix_separator, int *local_truth, std::vector< Ioss::Field > &fields)
Definition: Ioss_Utils.C:730
static T find_index_location(T node, const std::vector< T > &index)
Definition: Ioss_Utils.h:135
static std::string fixup_type(const std::string &base, int nodes_per_element, int spatial)
Process the base element type 'base' which has 'nodes_per_element' nodes and a spatial dimension of '...
Definition: Ioss_Utils.C:349
static bool check_block_order(const std::vector< T * > &blocks)
Definition: Ioss_Utils.h:229
static std::string platform_information()
Get a string containing 'uname' output.
Definition: Ioss_Utils.C:856
static size_t get_number(const std::string &suffix)
Definition: Ioss_Utils.C:286
static void check_non_null(void *ptr, const char *type, const std::string &name, const std::string &func)
Definition: Ioss_Utils.C:257
static void delete_name_array(char **names, int count)
Definition: Ioss_Utils.C:328
static void copy_string(char *dest, char const *source, size_t elements)
Definition: Ioss_Utils.C:1493
const size_t max_line_length
Definition: Iofx_DatabaseIO.C:97
static void copy_database(Ioss::Region &region, Ioss::Region &output_region, Ioss::MeshCopyOptions &options)
Definition: Ioss_Utils.C:1522
static void time_and_date(char *time_string, char *date_string, size_t length)
Get formatted time and date strings.
Definition: Ioss_Utils.C:241
A grouping entity that contains other grouping entities.
Definition: Ioss_Region.h:98
static void calculate_sideblock_membership(IntVector &face_is_member, const SideBlock *ef_blk, size_t int_byte_size, const void *element, const void *sides, int64_t number_sides, const Region *region)
Definition: Ioss_Utils.C:976
static std::string local_filename(const std::string &relative_filename, const std::string &type, const std::string &working_directory)
Get a filename relative to the specified working directory (if any) of the current execution.
Definition: Ioss_Utils.C:428
std::string name(Ioss::GroupingEntity *entity)
Definition: io_info.C:87
static double timer()
Definition: Ioss_Utils.C:1117
static int64_t extract_id(const std::string &name_id)
Definition: Ioss_Utils.C:296
Holds metadata for bulk data associated with a GroupingEntity.
Definition: Ioss_Field.h:47
static int field_warning(const Ioss::GroupingEntity *ge, const Ioss::Field &field, const std::string &inout)
Definition: Ioss_Utils.C:440
static void uniquify(std::vector< T > &vec, bool skip_first=false)
Definition: Ioss_Utils.h:113
static void generate_history_mesh(Ioss::Region *region)
Create a nominal mesh for use in history databases.
Definition: Ioss_Utils.C:1461
static char ** get_name_array(size_t count, int size)
Definition: Ioss_Utils.C:318
A collection of Ioss::Property objects.
Definition: Ioss_PropertyManager.h:49
entity_type
Definition: Iovs_DatabaseIO.C:81
static size_t get_hwm_memory_info()
Definition: Ioss_Utils.C:928
static void copy_string(char(&output)[size], const std::string &source)
Definition: Ioss_Utils.h:175
static std::string decode_filename(const std::string &filename, int processor, int num_processors)
Definition: Ioss_Utils.C:269
static void generate_index(std::vector< T > &index)
Definition: Ioss_Utils.h:124
static int log_power_2(uint64_t value)
Definition: Ioss_Utils.C:1509
static void clear(std::vector< T > &vec)
Definition: Ioss_Utils.h:186