LCOV - code coverage report
Current view: top level - include/mesh - exodusII_io_helper.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4490 (fb4270) with base e59def Lines: 36 38 94.7 %
Date: 2026-07-23 17:02:07 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : #ifndef LIBMESH_EXODUSII_IO_HELPER_H
      19             : #define LIBMESH_EXODUSII_IO_HELPER_H
      20             : 
      21             : #include "libmesh/libmesh_config.h"
      22             : 
      23             : #ifdef LIBMESH_HAVE_EXODUS_API
      24             : 
      25             : // Local includes
      26             : #include "libmesh/parallel_object.h"
      27             : #include "libmesh/point.h"
      28             : #include "libmesh/boundary_info.h" // BoundaryInfo::BCTuple
      29             : #include "libmesh/enum_elem_type.h" // INVALID_ELEM
      30             : #include "libmesh/exodus_header_info.h"
      31             : 
      32             : // C++ includes
      33             : #include <iostream>
      34             : #include <string>
      35             : #include <vector>
      36             : #include <map>
      37             : 
      38             : // Macros to simplify checking Exodus error codes
      39             : #define EX_CHECK_ERR(code, msg)                 \
      40             :   do {                                          \
      41             :     if ((code) < 0) {                           \
      42             :       libmesh_error_msg((msg));                 \
      43             :     } } while (0)
      44             : 
      45             : #define EX_EXCEPTIONLESS_CHECK_ERR(code, msg)   \
      46             :   do {                                          \
      47             :     if ((code) < 0) {                           \
      48             :       libMesh::err << (msg) << std::endl;       \
      49             :       libmesh_exceptionless_error();            \
      50             :     } } while (0)
      51             : 
      52             : // Before we include a header wrapped in a namespace, we'd better make
      53             : // sure none of its dependencies end up in that namespace
      54             : #include <errno.h>
      55             : #include <stddef.h>
      56             : #include <stdlib.h>
      57             : #include <stdint.h>
      58             : 
      59             : namespace libMesh
      60             : {
      61             : 
      62             : // Forward declarations
      63             : class MeshBase;
      64             : class DofObject;
      65             : 
      66             : /**
      67             :  * This is the \p ExodusII_IO_Helper class.  This class hides the
      68             :  * implementation details of interfacing with the Exodus binary
      69             :  * format.
      70             :  *
      71             :  * \author John W. Peterson
      72             :  * \date 2002
      73             :  */
      74       10066 : class ExodusII_IO_Helper : public ParallelObject
      75             : {
      76             : public:
      77             :   /**
      78             :    * Constructor. Automatically initializes all the private members of
      79             :    * the class.  Also allows you to set the verbosity level to v=true
      80             :    * (on) or v=false (off).  The second argument, if true, tells the class to only
      81             :    * perform its actions if running on processor zero.  If you initialize this
      82             :    * to false, the writing methods will run on all processors instead.
      83             :    */
      84             :   ExodusII_IO_Helper(const ParallelObject & parent,
      85             :                      bool v=false,
      86             :                      bool run_only_on_proc0=true,
      87             :                      bool single_precision=false);
      88             :   /**
      89             :    * Special functions. This class does not manage any dynamically
      90             :    * allocated resources (file pointers, etc.) so it _should_ be
      91             :    * default copy/move constructable, but I don't know
      92             :    * if any existing code actually uses these operations.
      93             :    */
      94             :   ExodusII_IO_Helper (const ExodusII_IO_Helper &) = default;
      95             :   ExodusII_IO_Helper (ExodusII_IO_Helper &&) = default;
      96             :   virtual ~ExodusII_IO_Helper();
      97             : 
      98             :   /**
      99             :    * This class contains references so it can't be default
     100             :    * copy/move-assigned.
     101             :    */
     102             :   ExodusII_IO_Helper & operator= (const ExodusII_IO_Helper &) = delete;
     103             :   ExodusII_IO_Helper & operator= (ExodusII_IO_Helper &&) = delete;
     104             : 
     105             :   /**
     106             :    * \returns The ExodusII API version, in "nodot" format; e.g. 822
     107             :    * for 8.22
     108             :    */
     109             :   static int get_exodus_version();
     110             : 
     111             :   /**
     112             :    * \returns The current element type.
     113             :    *
     114             :    * \note The default behavior is for this value to be in all capital
     115             :    * letters, e.g. \p HEX27.
     116             :    */
     117             :   const char * get_elem_type() const;
     118             : 
     119             :   /**
     120             :    * Sets whether or not to write extra "side" elements.  This is useful for
     121             :    * plotting SIDE_DISCONTINUOUS data.
     122             :    */
     123             :   void set_add_sides(bool add_sides);
     124             : 
     125             :   bool get_add_sides();
     126             : 
     127             :   /**
     128             :    * Opens an \p ExodusII mesh file named \p filename.  If
     129             :    * read_only==true, the file will be opened with the EX_READ flag,
     130             :    * otherwise it will be opened with the EX_WRITE flag.
     131             :    */
     132             :   void open(const char * filename, bool read_only);
     133             : 
     134             :   /**
     135             :    * Reads an \p ExodusII mesh file header, leaving this object's
     136             :    * internal data structures unchanged.
     137             :    */
     138             :   ExodusHeaderInfo read_header() const;
     139             : 
     140             :   /**
     141             :    * Reads an \p ExodusII mesh file header, and stores required
     142             :    * information on this object.
     143             :    */
     144             :   void read_and_store_header_info();
     145             : 
     146             :   /**
     147             :    * Reads the QA records from an ExodusII file.  We can use this to
     148             :    * detect when e.g. CUBIT 14+ was used to generate a Mesh file, and
     149             :    * work around certain known bugs in that version.
     150             :    */
     151             :   void read_qa_records();
     152             : 
     153             :   /**
     154             :    * Prints the \p ExodusII mesh file header, which includes the mesh
     155             :    * title, the number of nodes, number of elements, mesh dimension,
     156             :    * number of sidesets, and number of nodesets.
     157             :    */
     158             :   void print_header();
     159             : 
     160             :   /**
     161             :    * Reads the nodal data (x,y,z coordinates) from the \p ExodusII
     162             :    * mesh file.
     163             :    */
     164             :   void read_nodes();
     165             : 
     166             :   /**
     167             :    * Reads the optional \p node_num_map from the \p ExodusII mesh
     168             :    * file.
     169             :    */
     170             :   void read_node_num_map();
     171             : 
     172             :   /**
     173             :    * Reads the optional \p bex_cv_blocks from the \p ExodusII mesh
     174             :    * file.
     175             :    */
     176             :   void read_bex_cv_blocks();
     177             : 
     178             :   /**
     179             :    * Prints the nodal information, by default to \p libMesh::out.
     180             :    */
     181             :   void print_nodes(std::ostream & out_stream = libMesh::out);
     182             : 
     183             :   /**
     184             :    * Reads information for all of the blocks in the \p ExodusII mesh
     185             :    * file.
     186             :    */
     187             :   void read_block_info();
     188             : 
     189             :   /**
     190             :    * Get the block number for the given block index.
     191             :    */
     192             :   int get_block_id(int index);
     193             : 
     194             :   /**
     195             :    * Get the block name for the given block index if supplied in
     196             :    * the mesh file.  Otherwise an empty string is returned.
     197             :    */
     198             :   std::string get_block_name(int index);
     199             : 
     200             :   /**
     201             :    * Get the side set id for the given side set index.
     202             :    */
     203             :   int get_side_set_id(int index);
     204             : 
     205             :   /**
     206             :    * Get the side set name for the given side set index if supplied in
     207             :    * the mesh file.  Otherwise an empty string is returned.
     208             :    */
     209             :   std::string get_side_set_name(int index);
     210             : 
     211             :   /**
     212             :    * Get the node set id for the given node set index.
     213             :    */
     214             :   int get_node_set_id(int index);
     215             : 
     216             :   /**
     217             :    * Get the node set name for the given node set index if supplied in
     218             :    * the mesh file.  Otherwise an empty string is returned.
     219             :    */
     220             :   std::string get_node_set_name(int index);
     221             : 
     222             :   /**
     223             :    * Reads all of the element connectivity for block \p block in the
     224             :    * \p ExodusII mesh file.
     225             :    */
     226             :   void read_elem_in_block(int block);
     227             : 
     228             :   /**
     229             :    * Reads NSIDED face blocks used by NFACED element blocks.
     230             :    */
     231             :   void read_face_blocks();
     232             : 
     233             :   /**
     234             :    * Read in edge blocks, storing information in the BoundaryInfo object.
     235             :    */
     236             :   void read_edge_blocks(MeshBase & mesh);
     237             : 
     238             :   /**
     239             :    * Reads the optional \p node_num_map from the \p ExodusII mesh
     240             :    * file.
     241             :    */
     242             :   void read_elem_num_map();
     243             : 
     244             :   /**
     245             :    * Reads information about all of the sidesets in the \p ExodusII
     246             :    * mesh file.
     247             :    */
     248             :   void read_sideset_info();
     249             : 
     250             :   /**
     251             :    * Reads information about all of the nodesets in the \p ExodusII
     252             :    * mesh file.
     253             :    */
     254             :   void read_nodeset_info();
     255             : 
     256             :   /**
     257             :    * Reads information about all of the elemsets in the \p ExodusII
     258             :    * mesh file.
     259             :    */
     260             :   void read_elemset_info();
     261             : 
     262             :   /**
     263             :    * Reads information about sideset \p id and inserts it into the
     264             :    * global sideset array at the position \p offset.
     265             :    */
     266             :   void read_sideset(int id, int offset);
     267             : 
     268             :   /**
     269             :    * Reads information about elemset \p id and inserts it into the
     270             :    * global elemset array at the position \p offset.
     271             :    */
     272             :   void read_elemset(int id, int offset);
     273             : 
     274             :   /**
     275             :    * New API that reads all nodesets simultaneously. This may be slightly
     276             :    * faster than reading them one at a time. Calls ex_get_concat_node_sets()
     277             :    * under the hood.
     278             :    */
     279             :   void read_all_nodesets();
     280             : 
     281             :   /**
     282             :    * Closes the \p ExodusII mesh file.
     283             :    *
     284             :    * This function is called from the ExodusII_IO destructor, so it should
     285             :    * not throw an exception.
     286             :    */
     287             :   void close() noexcept;
     288             : 
     289             :   /**
     290             :    * Reads and stores the timesteps in the 'time_steps' array.
     291             :    */
     292             :   void read_time_steps();
     293             : 
     294             :   /**
     295             :    * Reads the number of timesteps currently stored in the Exodus file
     296             :    * and stores it in the num_time_steps variable.
     297             :    */
     298             :   void read_num_time_steps();
     299             : 
     300             :   /**
     301             :    * Reads the nodal values for the variable 'nodal_var_name' at the
     302             :    * specified time into the 'nodal_var_values' array.
     303             :    */
     304             :   void read_nodal_var_values(std::string nodal_var_name, int time_step);
     305             : 
     306             :   /**
     307             :    * Reads elemental values for the variable 'elemental_var_name' at the
     308             :    * specified timestep into the 'elem_var_value_map' which is passed in.
     309             :    */
     310             :   void read_elemental_var_values(std::string elemental_var_name,
     311             :                                  int time_step,
     312             :                                  std::map<dof_id_type, Real> & elem_var_value_map);
     313             : 
     314             :   /**
     315             :    * Helper function that takes a (1-based) Exodus node/elem id and
     316             :    * determines the corresponding libMesh Node/Elem id. Takes into account
     317             :    * whether the user has chosen to set the Node/Elem unique ids based on
     318             :    * the {node,elem}_num_map or to let libMesh set them.
     319             :    */
     320             :   dof_id_type get_libmesh_node_id(int exodus_node_id);
     321             :   dof_id_type get_libmesh_elem_id(int exodus_elem_id);
     322             : 
     323             :   /**
     324             :    * Helper function that conditionally sets the unique_id of the
     325             :    * passed-in Node/Elem.  Calling this function does nothing if
     326             :    * _set_unique_ids_from_maps == false, otherwise it sets the
     327             :    * unique_id based on the entries of the {node,elem_num_map}.  The
     328             :    * input index is assumed to be a zero-based index into the
     329             :    * {node,elem}_num_map array.
     330             :    */
     331             :   void conditionally_set_node_unique_id(
     332             :     MeshBase & mesh, Node * node, int zero_based_node_num_map_index);
     333             :   void conditionally_set_elem_unique_id(
     334             :     MeshBase & mesh, Elem * elem, int zero_based_elem_num_map_index);
     335             : 
     336             : private:
     337             : 
     338             :   /**
     339             :    * Internal implementation for the two sets of functions above.
     340             :    */
     341             :   dof_id_type get_libmesh_id(
     342             :     int exodus_id,
     343             :     const std::vector<int> & num_map);
     344             : 
     345             :   void set_dof_object_unique_id(
     346             :     MeshBase & mesh,
     347             :     DofObject * dof_object,
     348             :     int exodus_mapped_id);
     349             : 
     350             : public:
     351             : 
     352             :   /**
     353             :    * Opens an \p ExodusII mesh file named \p filename for writing.
     354             :    */
     355             :   virtual void create(std::string filename);
     356             : 
     357             :   /**
     358             :    * Initializes the Exodus file.
     359             :    */
     360             :   virtual void initialize(std::string title, const MeshBase & mesh, bool use_discontinuous=false);
     361             : 
     362             :   /**
     363             :    * Writes the nodal coordinates contained in "mesh"
     364             :    */
     365             :   virtual void write_nodal_coordinates(const MeshBase & mesh, bool use_discontinuous=false);
     366             : 
     367             :   /**
     368             :    * Writes the elements contained in "mesh". FIXME: This only works
     369             :    * for Meshes having a single type of element in each subdomain!
     370             :    *
     371             :    * If \p use_discontinuous is true, we break apart elements, so that
     372             :    * shared nodes on faces/edges/vertices can take different values
     373             :    * from different elements.  This is useful for plotting
     374             :    * discontinuous underlying variables
     375             :    *
     376             :    * If \p _add_sides is true, we also output side elements, so that
     377             :    * shared nodes on edges/vertices can take different values from
     378             :    * different elements.  This is useful for plotting
     379             :    * SIDE_DISCONTINUOUS representing e.g. inter-element fluxes.
     380             :    */
     381             :   virtual void write_elements(const MeshBase & mesh,
     382             :                               bool use_discontinuous=false);
     383             : 
     384             :   /**
     385             :    * Writes the sidesets contained in "mesh"
     386             :    */
     387             :   virtual void write_sidesets(const MeshBase & mesh);
     388             : 
     389             :   /**
     390             :    * Writes the nodesets contained in "mesh"
     391             :    */
     392             :   virtual void write_nodesets(const MeshBase & mesh);
     393             : 
     394             :   /**
     395             :    * Sets up the nodal variables
     396             :    */
     397             :   virtual void initialize_element_variables(std::vector<std::string> names,
     398             :                                             const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains);
     399             : 
     400             :   /**
     401             :    * Sets up the nodal variables
     402             :    */
     403             :   void initialize_nodal_variables(std::vector<std::string> names);
     404             : 
     405             :   /**
     406             :    * Sets up the global variables
     407             :    */
     408             :   void initialize_global_variables(std::vector<std::string> names);
     409             : 
     410             :   /**
     411             :    * Writes the time for the timestep
     412             :    */
     413             :   void write_timestep(int timestep, Real time);
     414             : 
     415             :   /**
     416             :    * Write elemsets stored on the Mesh to the exo file.
     417             :    */
     418             :   void write_elemsets(const MeshBase & mesh);
     419             : 
     420             :   /**
     421             :    * Write sideset data for the requested timestep.
     422             :    */
     423             :   void
     424             :   write_sideset_data (const MeshBase & mesh,
     425             :                       int timestep,
     426             :                       const std::vector<std::string> & var_names,
     427             :                       const std::vector<std::set<boundary_id_type>> & side_ids,
     428             :                       const std::vector<std::map<BoundaryInfo::BCTuple, Real>> & bc_vals);
     429             : 
     430             :   /**
     431             :    * Read sideset variables, if any, into the provided data structures.
     432             :    */
     433             :   void
     434             :   read_sideset_data (const MeshBase & mesh,
     435             :                      int timestep,
     436             :                      std::vector<std::string> & var_names,
     437             :                      std::vector<std::set<boundary_id_type>> & side_ids,
     438             :                      std::vector<std::map<BoundaryInfo::BCTuple, Real>> & bc_vals);
     439             : 
     440             :   /**
     441             :    * Similar to read_sideset_data(), but instead of creating one
     442             :    * std::map per sideset per variable, creates a single map of (elem,
     443             :    * side, boundary_id) tuples, and stores the exo file array indexing
     444             :    * for any/all sideset variables on that sideset (they are all the
     445             :    * same). This function does not actually call exII::ex_get_sset_var()
     446             :    * to get values, and can be useful if only the original ordering of
     447             :    * (elem, side) pairs in the exo file is required in cases where a
     448             :    * separate approach is used to read the sideset data arrays.
     449             :    */
     450             :   void
     451             :   get_sideset_data_indices (const MeshBase & mesh,
     452             :                             std::map<BoundaryInfo::BCTuple, unsigned int> & bc_array_indices);
     453             : 
     454             :   /**
     455             :    * Write nodeset data for the requested timestep.
     456             :    */
     457             :   void
     458             :   write_nodeset_data (int timestep,
     459             :                       const std::vector<std::string> & var_names,
     460             :                       const std::vector<std::set<boundary_id_type>> & node_boundary_ids,
     461             :                       const std::vector<std::map<BoundaryInfo::NodeBCTuple, Real>> & bc_vals);
     462             : 
     463             :   /**
     464             :    * Read nodeset variables, if any, into the provided data structures.
     465             :    */
     466             :   void
     467             :   read_nodeset_data (int timestep,
     468             :                      std::vector<std::string> & var_names,
     469             :                      std::vector<std::set<boundary_id_type>> & node_boundary_ids,
     470             :                      std::vector<std::map<BoundaryInfo::NodeBCTuple, Real>> & bc_vals);
     471             : 
     472             :   /**
     473             :    * Similar to read_nodeset_data(), but instead of creating one
     474             :    * std::map per nodeset per variable, creates a single map of
     475             :    * (node_id, boundary_id) tuples, and stores the exo file array
     476             :    * indexing for any/all nodeset variables on that nodeset (they are
     477             :    * all the same).
     478             :    */
     479             :   void
     480             :   get_nodeset_data_indices (std::map<BoundaryInfo::NodeBCTuple, unsigned int> & bc_array_indices);
     481             : 
     482             :   /**
     483             :    * Write elemset data for the requested timestep.
     484             :    */
     485             :   void
     486             :   write_elemset_data (int timestep,
     487             :                       const std::vector<std::string> & var_names,
     488             :                       const std::vector<std::set<elemset_id_type>> & elemset_ids_in,
     489             :                       const std::vector<std::map<std::pair<dof_id_type, elemset_id_type>, Real>> & elemset_vals);
     490             : 
     491             :   /**
     492             :    * Read elemset variables, if any, into the provided data structures.
     493             :    */
     494             :   void
     495             :   read_elemset_data (int timestep,
     496             :                      std::vector<std::string> & var_names,
     497             :                      std::vector<std::set<elemset_id_type>> & elemset_ids_in,
     498             :                      std::vector<std::map<std::pair<dof_id_type, elemset_id_type>, Real>> & elemset_vals);
     499             : 
     500             :   /**
     501             :    * Similar to read_elemset_data(), but instead of creating one
     502             :    * std::map per elemset per variable, creates a single map of
     503             :    * (elem_id, elemset_id) tuples, and stores the exo file array
     504             :    * indexing for any/all elemset variables on that elemset (they are
     505             :    * all the same).
     506             :    */
     507             :   void
     508             :   get_elemset_data_indices (std::map<std::pair<dof_id_type, elemset_id_type>, unsigned int> & elemset_array_indices);
     509             : 
     510             :   /**
     511             :    * Writes the vector of values to the element variables.
     512             :    *
     513             :    * The 'values' vector is assumed to be in the order:
     514             :    * {(u1, u2, u3, ..., uN), (v1, v2, v3, ..., vN), (w1, w2, w3, ..., wN)}
     515             :    * where N is the number of elements.
     516             :    *
     517             :    * This ordering is produced by calls to ES::build_elemental_solution_vector().
     518             :    * ES::build_discontinuous_solution_vector(), on the other hand, produces an
     519             :    * element-major ordering. See the function below for that case.
     520             :    */
     521             :   void write_element_values
     522             :   (const MeshBase & mesh,
     523             :    const std::vector<Real> & values,
     524             :    int timestep,
     525             :    const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains);
     526             : 
     527             :   /**
     528             :    * Same as the function above, but assume the input 'values' vector is
     529             :    * in element-major order, i.e.
     530             :    * {(u1,v1,w1), (u2,v2,w2), ... (uN,vN,wN)}
     531             :    * This function is called by
     532             :    * ExodusII_IO::write_element_data_from_discontinuous_nodal_data()
     533             :    * because ES::build_discontinuous_solution_vector() builds the solution
     534             :    * vector in this order.
     535             :    *
     536             :    * \note If some variables are subdomain-restricted, then the tuples will
     537             :    * be of different lengths for each element, i.e.
     538             :    * {(u1,v1,w1), (u2,v2), ... (uN,vN,wN)}
     539             :    * if variable w is not active on element 2.
     540             :    */
     541             :   void write_element_values_element_major
     542             :   (const MeshBase & mesh,
     543             :    const std::vector<Real> & values,
     544             :    int timestep,
     545             :    const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains,
     546             :    const std::vector<std::string> & derived_var_names,
     547             :    const std::map<subdomain_id_type, std::vector<std::string>> & subdomain_to_var_names);
     548             : 
     549             :   /**
     550             :    * Writes the vector of values to a nodal variable.
     551             :    */
     552             :   void write_nodal_values(int var_id, const std::vector<Real> & values, int timestep);
     553             : 
     554             :   /**
     555             :    * Writes the vector of information records.
     556             :    */
     557             :   void write_information_records(const std::vector<std::string> & records);
     558             : 
     559             :   /**
     560             :    * Writes the vector of global variables.
     561             :    */
     562             :   void write_global_values(const std::vector<Real> & values, int timestep);
     563             : 
     564             :   /**
     565             :    * Uses ex_update() to flush buffers to file.
     566             :    */
     567             :   void update();
     568             : 
     569             :   /**
     570             :    * Reads the vector of global variables.
     571             :    */
     572             :   void read_global_values(std::vector<Real> & values, int timestep);
     573             : 
     574             :   /**
     575             :    * Sets the underlying value of the boolean flag
     576             :    * _use_mesh_dimension_instead_of_spatial_dimension.  By default,
     577             :    * the value of this flag is false.
     578             :    *
     579             :    * See the ExodusII_IO class documentation for a detailed
     580             :    * description of this flag.
     581             :    */
     582             :   void use_mesh_dimension_instead_of_spatial_dimension(bool val);
     583             : 
     584             :   /**
     585             :    * Set to true (the default) to write files in an HDF5-based file
     586             :    * format (when HDF5 is available), or to false to write files in
     587             :    * the old NetCDF3-based format.  If HDF5 is unavailable, this
     588             :    * setting does nothing.
     589             :    */
     590             :   void set_hdf5_writing(bool write_hdf5);
     591             : 
     592             :   /**
     593             :    * Sets the value of _write_as_dimension.
     594             :    *
     595             :    * This directly controls the num_dim which is written to the Exodus
     596             :    * file.  If non-zero, this value supersedes all other dimensions,
     597             :    * including:
     598             :    * 1.) MeshBase::spatial_dimension()
     599             :    * 2.) MeshBase::mesh_dimension()
     600             :    * 3.) Any value passed to use_mesh_dimension_instead_of_spatial_dimension()
     601             :    * This is useful/necessary for working around a bug in Paraview which
     602             :    * prevents the "Plot Over Line" filter from working on 1D meshes.
     603             :    */
     604             :   void write_as_dimension(unsigned dim);
     605             : 
     606             :   /**
     607             :    * Allows you to set a vector that is added to the coordinates of all
     608             :    * of the nodes.  Effectively, this "moves" the mesh to a particular position
     609             :    */
     610             :   void set_coordinate_offset(Point p);
     611             : 
     612             :   /**
     613             :    * Set how many characters to use in names when opening a file for
     614             :    * writing.
     615             :    */
     616             :   void set_max_name_length(unsigned int max_length);
     617             : 
     618             :   /**
     619             :    * \returns A vector with three copies of each element in the provided name vector,
     620             :    * starting with r_, i_ and a_ respectively. If the "write_complex_abs" parameter
     621             :    * is true (default), the complex modulus is written, otherwise only the real and
     622             :    * imaginary parts are written.
     623             :    */
     624             :   std::vector<std::string>
     625             :   get_complex_names(const std::vector<std::string> & names,
     626             :                     bool write_complex_abs) const;
     627             : 
     628             :   /**
     629             :    * returns a "tripled" copy of \p vars_active_subdomains, which is necessary in the
     630             :    * complex-valued case.
     631             :    */
     632             :   std::vector<std::set<subdomain_id_type>>
     633             :   get_complex_vars_active_subdomains
     634             :   (const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains,
     635             :    bool write_complex_abs) const;
     636             : 
     637             :   /**
     638             :    * Takes a map from subdomain id -> vector of active variable names
     639             :    * as input and returns a corresponding map where the original
     640             :    * variable names have been replaced by their complex counterparts.
     641             :    * Used by the ExodusII_IO::write_element_data_from_discontinuous_nodal_data()
     642             :    * function.
     643             :    */
     644             :   std::map<subdomain_id_type, std::vector<std::string>>
     645             :   get_complex_subdomain_to_var_names
     646             :   (const std::map<subdomain_id_type, std::vector<std::string>> & subdomain_to_var_names,
     647             :    bool write_complex_abs) const;
     648             : 
     649             :   /**
     650             :    * This is the \p ExodusII_IO_Helper Conversion class.  It provides
     651             :    * a data structure which contains \p ExodusII node/edge maps and
     652             :    * name conversions.  It's defined below.
     653             :    */
     654             :   class Conversion;
     655             : 
     656             :   /**
     657             :    * This is the \p ExodusII_IO_Helper NamesData class.
     658             :    * It manages the C data structure necessary for writing out named
     659             :    * entities to ExodusII files.
     660             :    */
     661             :   class NamesData;
     662             : 
     663             :   /**
     664             :    * Prints the message defined in \p msg. Can be turned off if
     665             :    * verbosity is set to 0.
     666             :    */
     667             :   void message(std::string_view msg);
     668             : 
     669             :   /**
     670             :    * Prints the message defined in \p msg, and appends the number \p i
     671             :    * to the end of the message.  Useful for printing messages in
     672             :    * loops.  Can be turned off if verbosity is set to 0.
     673             :    */
     674             :   void message(std::string_view msg, int i);
     675             : 
     676             :   // File identification flag
     677             :   int ex_id;
     678             : 
     679             :   // General error flag
     680             :   int ex_err;
     681             : 
     682             :   // struct which contains data fields from the Exodus file header
     683             :   ExodusHeaderInfo header_info;
     684             : 
     685             :   // Problem title (Use vector<char> to emulate a char *)
     686             :   std::vector<char> & title;
     687             : 
     688             :   // Number of dimensions in the mesh
     689             :   int & num_dim;
     690             : 
     691             :   // Total number of nodes in the mesh
     692             :   int & num_nodes;
     693             : 
     694             :   // Total number of elements in the mesh
     695             :   int & num_elem;
     696             : 
     697             :   // Smallest element id which exceeds every element id in the mesh.
     698             :   // (this may exceed num_elem due to mapping)
     699             :   int end_elem_id() const;
     700             : 
     701             :   // Total number of element blocks
     702             :   int & num_elem_blk;
     703             : 
     704             :   // Total number of edges
     705             :   int & num_edge;
     706             : 
     707             :   // Total number of edge blocks. The sum of the number of edges in
     708             :   // each block must equal num_edge.
     709             :   int & num_edge_blk;
     710             : 
     711             :   // Total number of faces
     712             :   int & num_face;
     713             : 
     714             :   // Total number of face blocks. The sum of the number of faces in
     715             :   // each block must equal num_face.
     716             :   int & num_face_blk;
     717             : 
     718             :   // Total number of node sets
     719             :   int & num_node_sets;
     720             : 
     721             :   // Total number of side sets
     722             :   int & num_side_sets;
     723             : 
     724             :   // Total number of element sets
     725             :   int & num_elem_sets;
     726             : 
     727             :   // Number of global variables
     728             :   int num_global_vars;
     729             : 
     730             :   // Number of sideset variables
     731             :   int num_sideset_vars;
     732             : 
     733             :   // Number of nodeset variables
     734             :   int num_nodeset_vars;
     735             : 
     736             :   // Number of elemset variables
     737             :   int num_elemset_vars;
     738             : 
     739             :   // Number of elements in this block
     740             :   int num_elem_this_blk;
     741             : 
     742             :   // Number of nodes in each element
     743             :   int num_nodes_per_elem;
     744             : 
     745             :   // Number of attributes for a given block
     746             :   int num_attr;
     747             : 
     748             :   // Total number of elements in all side sets
     749             :   int num_elem_all_sidesets;
     750             : 
     751             :   // Total number of elements in all elem sets
     752             :   int num_elem_all_elemsets;
     753             : 
     754             :   // Vector of element block identification numbers
     755             :   std::vector<int> block_ids;
     756             : 
     757             :   // Vector of edge block identification numbers
     758             :   std::vector<int> edge_block_ids;
     759             : 
     760             :   // Vector of nodes in an element
     761             :   std::vector<int> connect;
     762             : 
     763             :   // For NSIDED element blocks, the number of nodes in each element
     764             :   std::vector<int> elem_node_counts;
     765             : 
     766             :   // For NFACED element blocks, the number of faces in each element
     767             :   std::vector<int> elem_face_counts;
     768             : 
     769             :   // For NFACED element blocks, the nodes in each Exodus face
     770             :   std::vector<std::vector<int>> c0polyhedron_face_connect;
     771             : 
     772             :   // Vector of the sideset IDs
     773             :   std::vector<int> ss_ids;
     774             : 
     775             :   // Vector of the nodeset IDs
     776             :   std::vector<int> nodeset_ids;
     777             : 
     778             :   // Vector of the elemset IDs
     779             :   std::vector<int> elemset_ids;
     780             : 
     781             :   // Number of sides in each sideset
     782             :   std::vector<int> num_sides_per_set;
     783             : 
     784             :   // Number of nodes in each nodeset
     785             :   std::vector<int> num_nodes_per_set;
     786             : 
     787             :   // Number of elems in each elemset
     788             :   std::vector<int> num_elems_per_set;
     789             : 
     790             :   // Number of distribution factors per sideset
     791             :   std::vector<int> num_df_per_set;
     792             : 
     793             :   // Number of distribution factors per nodeset
     794             :   std::vector<int> num_node_df_per_set;
     795             : 
     796             :   // Number of distribution factors per elemset
     797             :   std::vector<int> num_elem_df_per_set;
     798             : 
     799             :   // Starting indices for each nodeset in the node_sets_node_list vector.
     800             :   // Used in the calls to ex_{put,get}_concat_node_sets().
     801             :   std::vector<int> node_sets_node_index;
     802             : 
     803             :   // Starting indices for each nodeset in the node_sets_dist_fact vector.
     804             :   // Used in the calls to ex_{put,get}_concat_node_sets().
     805             :   std::vector<int> node_sets_dist_index;
     806             : 
     807             :   // Node ids for all nodes in nodesets, concatenated together.
     808             :   // Used in the calls to ex_{put,get}_concat_node_sets().
     809             :   std::vector<int> node_sets_node_list;
     810             : 
     811             :   // Distribution factors for all nodes in all nodesets, concatenated together.
     812             :   // Used in the calls to ex_{put,get}_concat_node_sets().
     813             :   std::vector<Real> node_sets_dist_fact;
     814             : 
     815             :   // List of element numbers in all sidesets
     816             :   std::vector<int> elem_list;
     817             : 
     818             :   // Side (face/edge) number actually on the boundary
     819             :   std::vector<int> side_list;
     820             : 
     821             :   // Side (face/edge) id number
     822             :   std::vector<int> id_list;
     823             : 
     824             :   // List of element numbers in all elemsets
     825             :   std::vector<int> elemset_list;
     826             : 
     827             :   // List of elemset ids for all elements in elemsets
     828             :   std::vector<int> elemset_id_list;
     829             : 
     830             :   // Optional mapping from internal [0,num_nodes) to arbitrary indices
     831             :   std::vector<int> node_num_map;
     832             : 
     833             :   // Optional mapping from internal [0,num_elem) to arbitrary indices
     834             :   std::vector<int> elem_num_map;
     835             : 
     836             :   // x locations of node points
     837             :   std::vector<Real> x;
     838             : 
     839             :   // y locations of node points
     840             :   std::vector<Real> y;
     841             : 
     842             :   // z locations of node points
     843             :   std::vector<Real> z;
     844             : 
     845             :   // Spline weights associated with node points, in IGA meshes
     846             :   std::vector<Real> w;
     847             : 
     848             :   // Number of Bezier Extraction coefficient vectors in a block
     849             :   unsigned int bex_num_elem_cvs;
     850             : 
     851             :   // Bezier Extraction connectivity indices, in IGA meshes
     852             :   std::vector<std::vector<long unsigned int>> bex_cv_conn;
     853             : 
     854             :   // Bezier Extraction coefficient vectors, in IGA meshes
     855             :   // bex_dense_constraint_vecs[block_num][vec_num][column_num] = coef
     856             :   std::vector<std::vector<std::vector<Real>>> bex_dense_constraint_vecs;
     857             : 
     858             :   // Type of element in a given block
     859             :   std::vector<char> elem_type;
     860             : 
     861             :   // Maps libMesh element numbers to Exodus element numbers
     862             :   // gets filled in when write_elements gets called
     863             :   std::map<dof_id_type, dof_id_type> libmesh_elem_num_to_exodus;
     864             :   std::vector<int> exodus_elem_num_to_libmesh;
     865             : 
     866             :   // Map of all node numbers connected to local node numbers to their exodus numbering.
     867             :   // The exodus numbers are stored in here starting with 1
     868             :   std::map<dof_id_type, dof_id_type> libmesh_node_num_to_exodus;
     869             :   std::vector<int> exodus_node_num_to_libmesh;
     870             : 
     871             :   // The number of timesteps in the file, as returned by ex_inquire
     872             :   int num_time_steps;
     873             : 
     874             :   // The timesteps stored in the solution file, filled by read_time_steps()
     875             :   std::vector<Real> time_steps;
     876             : 
     877             :   // The number of nodal variables in the Exodus file
     878             :   int num_nodal_vars;
     879             : 
     880             :   // The names of the nodal variables stored in the Exodus file
     881             :   std::vector<std::string> nodal_var_names;
     882             : 
     883             :   // Holds the nodal variable values for a given variable, one value
     884             :   // per node, indexed by libMesh node id.
     885             :   // This is a map so it can handle Nemesis files as well.
     886             :   std::map<dof_id_type, Real> nodal_var_values;
     887             : 
     888             :   // The number of elemental variables in the Exodus file
     889             :   int num_elem_vars;
     890             : 
     891             :   // The names of the elemental variables stored in the Exodus file
     892             :   std::vector<std::string> elem_var_names;
     893             : 
     894             :   // Holds the elemental variable values for a given variable, one value per element
     895             :   std::vector<Real> elem_var_values;
     896             : 
     897             :   // The names of the global variables stored in the Exodus file
     898             :   std::vector<std::string> global_var_names;
     899             : 
     900             :   // The names of the sideset variables stored in the Exodus file
     901             :   std::vector<std::string> sideset_var_names;
     902             : 
     903             :   // The names of the nodeset variables stored in the Exodus file
     904             :   std::vector<std::string> nodeset_var_names;
     905             : 
     906             :   // The names of the elemset variables stored in the Exodus file
     907             :   std::vector<std::string> elemset_var_names;
     908             : 
     909             :   // Maps of Ids to named entities
     910             :   std::map<int, std::string> id_to_block_names;
     911             :   std::map<int, std::string> id_to_edge_block_names;
     912             :   std::map<int, std::string> id_to_ss_names;
     913             :   std::map<int, std::string> id_to_ns_names;
     914             :   std::map<int, std::string> id_to_elemset_names;
     915             : 
     916             :   // On/Off message flag
     917             :   bool verbose;
     918             : 
     919             :   // Same as the ExodusII_IO flag by the same name. This flag is
     920             :   // also set whenever ExodusII_IO::set_unique_ids_from_maps() is called.
     921             :   bool set_unique_ids_from_maps;
     922             : 
     923             :   // This flag gets set after the Exodus file has been successfully opened for writing.
     924             :   // Both the create() and open() (if called with EX_WRITE) functions may set this flag.
     925             :   bool opened_for_writing;
     926             : 
     927             :   // This flag gets set after the open() function has been successfully called.
     928             :   // We call open() to open an ExodusII file for reading.
     929             :   bool opened_for_reading;
     930             : 
     931             :   // When either create() or open() is called, the Helper stores the
     932             :   // name of the opened file as current_filename.  This way, the
     933             :   // ExodusII_IO object can check to see if, on subsequent writes, the
     934             :   // user is asking to write to a *different* filename from the one
     935             :   // that is currently open, and signal an error.  The current
     936             :   // ExodusII_IO implementation is designed to work with a single file
     937             :   // only, so if you want to write to multiple Exodus files, use a
     938             :   // different ExodusII_IO object for each one.
     939             :   std::string current_filename;
     940             : 
     941             :   /**
     942             :    * Wraps calls to exII::ex_get_var_names() and exII::ex_get_var_param().
     943             :    * The enumeration controls whether nodal, elemental, global, etc.
     944             :    * variable names are read and which class members are filled in.
     945             :    * NODAL:     num_nodal_vars   nodal_var_names
     946             :    * ELEMENTAL: num_elem_vars    elem_var_names
     947             :    * GLOBAL:    num_global_vars  global_var_names
     948             :    * SIDESET:   num_sideset_vars sideset_var_names
     949             :    * NODESET:   num_nodeset_vars nodeset_var_names
     950             :    */
     951             :   enum ExodusVarType {NODAL=0, ELEMENTAL=1, GLOBAL=2, SIDESET=3, NODESET=4, ELEMSET=5};
     952             :   void read_var_names(ExodusVarType type);
     953             : 
     954             :   const ExodusII_IO_Helper::Conversion &
     955             :   get_conversion(const ElemType type) const;
     956             : 
     957             :   const ExodusII_IO_Helper::Conversion &
     958             :   get_conversion(std::string type_str) const;
     959             : 
     960             :   /*
     961             :    * Returns the sum of node "offsets" that are to be expected from a
     962             :    * parallel nodal solution vector that has had "fake" nodes added on
     963             :    * each processor.  This plus a node id gives a valid nodal solution
     964             :    * vector index.
     965             :    */
     966     8060701 :   dof_id_type node_id_to_vec_id(dof_id_type n) const
     967             :   {
     968     8060701 :     if (_added_side_node_offsets.empty())
     969     5963071 :       return n;
     970             : 
     971             :     // Find the processor id that has node_id in the parallel vec
     972        2410 :     const auto lb = std::upper_bound(_true_node_offsets.begin(),
     973        2410 :                                      _true_node_offsets.end(), n);
     974        1205 :     libmesh_assert(lb != _true_node_offsets.end());
     975        4820 :     const processor_id_type p = lb - _true_node_offsets.begin();
     976             : 
     977        4820 :     return n + (p ? _added_side_node_offsets[p-1] : 0);
     978             :   }
     979             : 
     980             :   /*
     981             :    * Returns the sum of both added node "offsets" on processors 0
     982             :    * through p-1 and real nodes added on processors 0 to p.
     983             :    * This is the starting index for added nodes' data.
     984             :    */
     985         125 :   dof_id_type added_node_offset_on(processor_id_type p) const
     986             :   {
     987          50 :     libmesh_assert (p < _true_node_offsets.size());
     988             :     const dof_id_type added_node_offsets =
     989         200 :       (_added_side_node_offsets.empty() || !p) ? 0 :
     990          75 :       _added_side_node_offsets[p-1];
     991         225 :     return _true_node_offsets[p] + added_node_offsets;
     992             :   }
     993             : 
     994             : 
     995             : protected:
     996             :   /**
     997             :    * When appending: during initialization, check that variable names
     998             :    * in the file match those you attempt to initialize with.
     999             :    */
    1000             :   void check_existing_vars(ExodusVarType type, std::vector<std::string> & names, std::vector<std::string> & names_from_file);
    1001             : 
    1002             :   /**
    1003             :    * Wraps calls to exII::ex_put_var_names() and exII::ex_put_var_param().
    1004             :    * The enumeration controls whether nodal, elemental, or global
    1005             :    * variable names are read and which class members are filled in.
    1006             :    */
    1007             :   void write_var_names(ExodusVarType type, const std::vector<std::string> & names);
    1008             : 
    1009             :   // If true, whenever there is an I/O operation, only perform if if we are on processor 0.
    1010             :   bool _run_only_on_proc0;
    1011             : 
    1012             :   // This flag gets set after the create() function has been successfully called.
    1013             :   bool _opened_by_create;
    1014             : 
    1015             :   // True once the elem vars are initialized
    1016             :   bool _elem_vars_initialized;
    1017             : 
    1018             :   // True once the global vars are initialized
    1019             :   bool _global_vars_initialized;
    1020             : 
    1021             :   // True once the nodal vars are initialized
    1022             :   bool _nodal_vars_initialized;
    1023             : 
    1024             :   // If true, use the Mesh's dimension (as determined by the dimension
    1025             :   // of the elements comprising the mesh) instead of the mesh's
    1026             :   // spatial dimension, when writing.  By default this is false.
    1027             :   bool _use_mesh_dimension_instead_of_spatial_dimension;
    1028             : 
    1029             :   // If true, write an HDF5 file when available.  If false, write the
    1030             :   // old format.
    1031             :   bool _write_hdf5;
    1032             : 
    1033             :   // The maximum name length to use when writing
    1034             :   unsigned int _max_name_length;
    1035             : 
    1036             :   // Set once the elem num map has been read
    1037             :   int _end_elem_id;
    1038             : 
    1039             :   // Use this for num_dim when writing the Exodus file.  If non-zero, supersedes
    1040             :   // any value set in _use_mesh_dimension_instead_of_spatial_dimension.
    1041             :   unsigned _write_as_dimension;
    1042             : 
    1043             :   // On output, shift every point by _coordinate_offset
    1044             :   Point _coordinate_offset;
    1045             : 
    1046             :   // If true, forces single precision I/O
    1047             :   bool _single_precision;
    1048             : 
    1049             :   /**
    1050             :    * If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS
    1051             :    * variables, _added_side_node_offsets[p] gives us the total
    1052             :    * solution vector offset to use on processor p+1 from the nodes on
    1053             :    * those previous ranks' sides.
    1054             :    */
    1055             :   std::vector<dof_id_type> _added_side_node_offsets;
    1056             : 
    1057             :   /**
    1058             :    * If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS
    1059             :    * variables, we also need to know how many real nodes from previous
    1060             :    * ranks are taking up space in a solution vector.
    1061             :    */
    1062             :   std::vector<dof_id_type> _true_node_offsets;
    1063             : 
    1064             :   /**
    1065             :    * This class facilitates inline conversion of an input data vector
    1066             :    * to a different precision level, depending on the underlying type
    1067             :    * of Real and whether or not the single_precision flag is set. This
    1068             :    * should be used whenever floating point data is being written to
    1069             :    * the Exodus file. Note that if no precision conversion has to take
    1070             :    * place, there should be very little overhead involved in using
    1071             :    * this object.
    1072             :    */
    1073             :   struct MappedOutputVector
    1074             :   {
    1075             :     // If necessary, allocates space to store a version of vec_in in a
    1076             :     // different precision than it was input with.
    1077             :     MappedOutputVector(const std::vector<Real> & vec_in,
    1078             :                        bool single_precision_in);
    1079             : 
    1080       13431 :     ~MappedOutputVector() = default;
    1081             : 
    1082             :     // Returns void * pointer to either the mapped data or the
    1083             :     // original data, as necessary.
    1084             :     void * data();
    1085             : 
    1086             :   private:
    1087             :     const std::vector<Real> & our_data;
    1088             :     bool single_precision;
    1089             :     std::vector<double> double_vec;
    1090             :     std::vector<float> float_vec;
    1091             :   };
    1092             : 
    1093             :   /**
    1094             :    * This class facilitates reading in vectors from Exodus file that
    1095             :    * may be of a different floating point type than Real. It employs
    1096             :    * basically the same approach as the MappedOutputVector, just going
    1097             :    * in the opposite direction. For more information, see the
    1098             :    * MappedOutputVector class docs.
    1099             :    */
    1100             :   struct MappedInputVector
    1101             :   {
    1102             :     MappedInputVector(std::vector<Real> & vec_in,
    1103             :                       bool single_precision_in);
    1104             :     ~MappedInputVector();
    1105             : 
    1106             :     // Returns void * pointer to either the mapped data or the
    1107             :     // original data, as necessary.
    1108             :     void * data();
    1109             : 
    1110             :   private:
    1111             :     std::vector<Real> & our_data;
    1112             :     bool single_precision;
    1113             :     std::vector<double> double_vec;
    1114             :     std::vector<float> float_vec;
    1115             :   };
    1116             : 
    1117             : 
    1118             : protected:
    1119             : 
    1120             :   /**
    1121             :    * read_var_names() dispatches to this function.  We need to
    1122             :    * override it slightly for Nemesis.
    1123             :    */
    1124             :   virtual void read_var_names_impl(const char * var_type,
    1125             :                                    int & count,
    1126             :                                    std::vector<std::string> & result);
    1127             : 
    1128             : private:
    1129             : 
    1130             :   /**
    1131             :    * Set to true iff we want to write separate "side" elements too.
    1132             :    */
    1133             :   bool _add_sides = false;
    1134             : 
    1135             :   /**
    1136             :    * write_var_names() dispatches to this function.
    1137             :    */
    1138             :   void write_var_names_impl(const char * var_type,
    1139             :                             int & count,
    1140             :                             const std::vector<std::string> & names);
    1141             : 
    1142             :   /**
    1143             :    * Defines equivalence classes of Exodus element types that map to
    1144             :    * libmesh ElemTypes.
    1145             :    */
    1146             :   std::map<std::string, ElemType> element_equivalence_map;
    1147             :   void init_element_equivalence_map();
    1148             : 
    1149             :   /**
    1150             :    * Associates libMesh ElemTypes with node/face/edge/etc. mappings
    1151             :    * of the corresponding Exodus element types.
    1152             :    *
    1153             :    * We have to map based on both ElemType and mesh dimension, because
    1154             :    * Exodus treats "TRI" side numbering in two different ways
    1155             :    * depending on whether a triangle is embedded in a 2D or a 3D mesh.
    1156             :    */
    1157             :   std::map<int, std::map<ElemType, ExodusII_IO_Helper::Conversion>> conversion_map;
    1158             :   void init_conversion_map();
    1159             : };
    1160             : 
    1161             : 
    1162             : 
    1163       91796 : class ExodusII_IO_Helper::Conversion
    1164             : {
    1165             : public:
    1166             : 
    1167             :   /**
    1168             :    * Constructor. Zero initializes all variables.
    1169             :    */
    1170      154018 :   Conversion()
    1171      154018 :     : node_map(nullptr),
    1172       91796 :       inverse_node_map(nullptr),
    1173       91796 :       side_map(nullptr),
    1174       91796 :       inverse_side_map(nullptr),
    1175       91796 :       shellface_map(nullptr),
    1176       91796 :       inverse_shellface_map(nullptr),
    1177       91796 :       shellface_index_offset(0),
    1178       91796 :       libmesh_type(INVALID_ELEM),
    1179       91796 :       dim(0),
    1180       91796 :       n_nodes(0),
    1181      154018 :       exodus_type("")
    1182      154018 :   {}
    1183             : 
    1184             :   /**
    1185             :    * \returns The ith component of the node map for this element.
    1186             :    *
    1187             :    * The node map maps the exodusII node numbering format to this
    1188             :    * library's format.
    1189             :    */
    1190             :   int get_node_map(int i) const;
    1191             : 
    1192             :   /**
    1193             :    * \returns The ith component of the inverse node map for this
    1194             :    * element.
    1195             :    *
    1196             :    * The inverse node map maps the libmesh node numbering to Exodus'
    1197             :    * node numbering.
    1198             :    *
    1199             :    * \note All elements except Hex27 currently have the same node
    1200             :    * numbering as libmesh elements.
    1201             :    */
    1202             :   int get_inverse_node_map(int i) const;
    1203             : 
    1204             :   /**
    1205             :    * \returns The ith component of the side map for this element.
    1206             :    *
    1207             :    * The side map maps the exodusII side numbering format to this
    1208             :    * library's format.
    1209             :    */
    1210             :   int get_side_map(int i) const;
    1211             : 
    1212             :   /**
    1213             :    * \returns The ith component of the side map for this element.
    1214             :    *
    1215             :    * The side map maps the libMesh side numbering format to this
    1216             :    * exodus's format.
    1217             :    */
    1218             :   int get_inverse_side_map(int i) const;
    1219             : 
    1220             :   /**
    1221             :    * \returns The ith component of the shellface map for this element.
    1222             :    * \note Nothing is currently using this.
    1223             :    */
    1224             :   int get_shellface_map(int i) const;
    1225             : 
    1226             :   /**
    1227             :    * \returns The ith component of the inverse shellface map for this element.
    1228             :    */
    1229             :   int get_inverse_shellface_map(int i) const;
    1230             : 
    1231             :   /**
    1232             :    * \returns The canonical element type for this element.
    1233             :    *
    1234             :    * The canonical element type is the standard element type
    1235             :    * understood by this library.
    1236             :    */
    1237             :   ElemType libmesh_elem_type() const;
    1238             : 
    1239             :   /**
    1240             :    * \returns The string corresponding to the Exodus type for this element.
    1241             :    */
    1242             :   std::string exodus_elem_type() const;
    1243             : 
    1244             :   /**
    1245             :    * \returns The shellface index offset.
    1246             :    */
    1247             :   std::size_t get_shellface_index_offset() const;
    1248             : 
    1249             :   /**
    1250             :    * An invalid_id that can be returned to signal failure in case
    1251             :    * something goes wrong.
    1252             :    */
    1253             :   static const int invalid_id;
    1254             : 
    1255             :   /**
    1256             :    * Pointer to the node map for this element.
    1257             :    */
    1258             :   const std::vector<int> * node_map;
    1259             : 
    1260             :   /**
    1261             :    * Pointer to the inverse node map for this element.
    1262             :    * For all elements except for the Hex27, this is the same
    1263             :    * as the node map.
    1264             :    */
    1265             :   const std::vector<int> * inverse_node_map;
    1266             : 
    1267             :   /**
    1268             :    * Pointer to the side map for this element.
    1269             :    */
    1270             :   const std::vector<int> * side_map;
    1271             : 
    1272             :   /**
    1273             :    * Pointer to the inverse side map for this element.
    1274             :    */
    1275             :   const std::vector<int> * inverse_side_map;
    1276             : 
    1277             :   /**
    1278             :    * Pointer to the shellface map for this element. Only the inverse
    1279             :    * is actually used currently, this one is provided for completeness
    1280             :    * and libmesh_ingore()d to avoid warnings.
    1281             :    */
    1282             :   const std::vector<int> * shellface_map;
    1283             : 
    1284             :   /**
    1285             :    * Pointer to the inverse shellface map for this element.
    1286             :    */
    1287             :   const std::vector<int> * inverse_shellface_map;
    1288             : 
    1289             :   /**
    1290             :    * The shellface index offset defines the offset due to a difference between libMesh
    1291             :    * and Exodus in indexing sidesets. This is relevant for shell elements, for
    1292             :    * example, since Exodus includes extra "shell face" sides in that case.
    1293             :    */
    1294             :   size_t shellface_index_offset;
    1295             : 
    1296             :   /**
    1297             :    * The canonical (i.e. standard for this library)
    1298             :    * element type.
    1299             :    */
    1300             :   ElemType libmesh_type;
    1301             : 
    1302             :   /**
    1303             :    * The element dimension; useful since we don't seem to have a cheap
    1304             :    * way to look this up from ElemType
    1305             :    */
    1306             :   int dim;
    1307             : 
    1308             :   /**
    1309             :    * The number of nodes per element; useful likewise
    1310             :    */
    1311             :   int n_nodes;
    1312             : 
    1313             :   /**
    1314             :    * The string corresponding to the Exodus type for this element
    1315             :    */
    1316             :   std::string exodus_type;
    1317             : };
    1318             : 
    1319             : 
    1320             : 
    1321             : /**
    1322             :  * This class is useful for managing anything that requires a char **
    1323             :  * input/output in ExodusII file.  You must know the number of strings
    1324             :  * and the length of each one at the time you create it.
    1325             :  */
    1326        4796 : class ExodusII_IO_Helper::NamesData
    1327             : {
    1328             : public:
    1329             :   /**
    1330             :    * Constructor.  Allocates enough storage to hold n_strings of
    1331             :    * length string_length.  (Actually allocates string_length+1 characters
    1332             :    * per string to account for the trailing '\0' character.)
    1333             :    */
    1334             :   explicit
    1335             :   NamesData(size_t n_strings, size_t string_length);
    1336             : 
    1337             :   /**
    1338             :    * Adds another name to the current data table.
    1339             :    */
    1340             :   void push_back_entry(const std::string & name);
    1341             : 
    1342             :   /**
    1343             :    * Provide access to the underlying C data table
    1344             :    */
    1345             :   char ** get_char_star_star();
    1346             : 
    1347             :   /**
    1348             :    * Provide access to the i'th underlying char *
    1349             :    */
    1350             :   char * get_char_star(int i);
    1351             : 
    1352             : private:
    1353             :   // C++ data structures for managing string memory
    1354             :   std::vector<std::vector<char>> data_table;
    1355             :   std::vector<char *> data_table_pointers;
    1356             : 
    1357             :   size_t counter;
    1358             :   size_t table_size;
    1359             : };
    1360             : 
    1361             : 
    1362          68 : inline void ExodusII_IO_Helper::set_add_sides(bool add_sides)
    1363             : {
    1364         238 :   _add_sides = add_sides;
    1365          68 : }
    1366             : 
    1367             : 
    1368        2752 : inline bool ExodusII_IO_Helper::get_add_sides()
    1369             : {
    1370        4811 :   return _add_sides;
    1371             : }
    1372             : 
    1373             : 
    1374           0 : inline int ExodusII_IO_Helper::end_elem_id() const
    1375             : {
    1376           0 :   libmesh_assert_equal_to(std::size_t(num_elem), elem_num_map.size());
    1377         357 :   return _end_elem_id;
    1378             : }
    1379             : 
    1380             : 
    1381             : } // namespace libMesh
    1382             : 
    1383             : #endif // LIBMESH_HAVE_EXODUS_API
    1384             : 
    1385             : #endif // LIBMESH_EXODUSII_IO_HELPER_H

Generated by: LCOV version 1.14