19 #include "libmesh/exodusII_io_helper.h" 
   22 #ifdef LIBMESH_HAVE_EXODUS_API 
   27 #include <unordered_map> 
   29 #include "libmesh/boundary_info.h" 
   30 #include "libmesh/enum_elem_type.h" 
   31 #include "libmesh/elem.h" 
   32 #include "libmesh/system.h" 
   33 #include "libmesh/numeric_vector.h" 
   34 #include "libmesh/enum_to_string.h" 
   35 #include "libmesh/enum_elem_type.h" 
   36 #include "libmesh/int_range.h" 
   37 #include "libmesh/utility.h" 
   40 #include "libmesh/mesh_tools.h"   
   50 const std::vector<int> trishell3_inverse_edge_map = {3, 4, 5};
 
   51 const std::vector<int> quadshell4_inverse_edge_map = {3, 4, 5, 6};
 
   56 const std::vector<int> hex27_node_map = {
 
   58   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
 
   60   21, 25, 24, 26, 23, 22, 20};
 
   63 const std::vector<int> hex27_inverse_node_map = {
 
   65   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
 
   67   26, 20, 25, 24, 22, 21, 23};
 
   71 const std::vector<int> tet_face_map = {1, 2, 3, 0};
 
   72 const std::vector<int> hex_face_map = {1, 2, 3, 4, 0, 5};
 
   73 const std::vector<int> prism_face_map = {1, 2, 3, 0, 4};
 
   76 const std::vector<int> tet_inverse_face_map = {4, 1, 2, 3};
 
   77 const std::vector<int> hex_inverse_face_map = {5, 1, 2, 3, 4, 6};
 
   78 const std::vector<int> prism_inverse_face_map = {4, 1, 2, 3, 5};
 
   81 const std::vector<int> hex_edge_map =
 
   82   {0,1,2,3,8,9,10,11,4,5,7,6};
 
   85 const std::vector<int> hex_inverse_edge_map =
 
   86   {1,2,3,4,9,10,12,11,5,6,7,8};
 
  100                                        bool run_only_on_proc0,
 
  101                                        bool single_precision) :
 
  115   num_elem_this_blk(0),
 
  116   num_nodes_per_elem(0),
 
  118   num_elem_all_sidesets(0),
 
  123   opened_for_writing(false),
 
  124   opened_for_reading(false),
 
  125   _run_only_on_proc0(run_only_on_proc0),
 
  126   _elem_vars_initialized(false),
 
  127   _global_vars_initialized(false),
 
  128   _nodal_vars_initialized(false),
 
  129   _use_mesh_dimension_instead_of_spatial_dimension(false),
 
  130   _write_as_dimension(0),
 
  131   _single_precision(single_precision)
 
  133   title.resize(MAX_LINE_LENGTH+1);
 
  151     conv.exodus_type = 
"SPHERE";
 
  155     conv.libmesh_type = 
EDGE2;
 
  156     conv.exodus_type = 
"EDGE2";
 
  160     conv.libmesh_type = 
EDGE3;
 
  161     conv.exodus_type = 
"EDGE3";
 
  165     conv.libmesh_type = 
QUAD4;
 
  166     conv.exodus_type = 
"QUAD4";
 
  170     conv.inverse_side_map = &quadshell4_inverse_edge_map;
 
  171     conv.shellface_index_offset = 2;
 
  173     conv.exodus_type = 
"SHELL4";
 
  177     conv.libmesh_type = 
QUAD8;
 
  178     conv.exodus_type = 
"QUAD8";
 
  182     conv.inverse_side_map = &quadshell4_inverse_edge_map;
 
  183     conv.shellface_index_offset = 2;
 
  185     conv.exodus_type = 
"SHELL8";
 
  189     conv.libmesh_type = 
QUAD9;
 
  190     conv.exodus_type = 
"QUAD9";
 
  194     conv.libmesh_type = 
TRI3;
 
  195     conv.exodus_type = 
"TRI3";
 
  199     conv.inverse_side_map = &trishell3_inverse_edge_map;
 
  200     conv.shellface_index_offset = 2;
 
  202     conv.exodus_type = 
"TRISHELL3";
 
  207     conv.exodus_type = 
"TRI3";
 
  211     conv.libmesh_type = 
TRI6;
 
  212     conv.exodus_type = 
"TRI6";
 
  216     conv.side_map = &hex_face_map;
 
  217     conv.inverse_side_map = &hex_inverse_face_map;
 
  218     conv.libmesh_type = 
HEX8;
 
  219     conv.exodus_type = 
"HEX8";
 
  223     conv.side_map = &hex_face_map;
 
  224     conv.inverse_side_map = &hex_inverse_face_map;
 
  225     conv.libmesh_type = 
HEX20;
 
  226     conv.exodus_type = 
"HEX20";
 
  230     conv.node_map = &hex27_node_map;
 
  231     conv.inverse_node_map = &hex27_inverse_node_map;
 
  232     conv.side_map = &hex_face_map;
 
  233     conv.inverse_side_map = &hex_inverse_face_map;
 
  234     conv.libmesh_type = 
HEX27;
 
  235     conv.exodus_type = 
"HEX27";
 
  239     conv.side_map = &tet_face_map;
 
  240     conv.inverse_side_map = &tet_inverse_face_map;
 
  241     conv.libmesh_type = 
TET4;
 
  242     conv.exodus_type = 
"TETRA4";
 
  246     conv.side_map = &tet_face_map;
 
  247     conv.inverse_side_map = &tet_inverse_face_map;
 
  248     conv.libmesh_type = 
TET10;
 
  249     conv.exodus_type = 
"TETRA10";
 
  253     conv.side_map = &prism_face_map;
 
  254     conv.inverse_side_map = &prism_inverse_face_map;
 
  255     conv.libmesh_type = 
PRISM6;
 
  256     conv.exodus_type = 
"WEDGE";
 
  260     conv.side_map = &prism_face_map;
 
  261     conv.inverse_side_map = &prism_inverse_face_map;
 
  263     conv.exodus_type = 
"WEDGE15";
 
  267     conv.side_map = &prism_face_map;
 
  268     conv.inverse_side_map = &prism_inverse_face_map;
 
  270     conv.exodus_type = 
"WEDGE18";
 
  275     conv.exodus_type = 
"PYRAMID5";
 
  280     conv.exodus_type = 
"PYRAMID13";
 
  285     conv.exodus_type = 
"PYRAMID14";
 
  392   std::transform(type_str.begin(), type_str.end(), type_str.begin(), ::toupper);
 
  418                    bool single_precision_in)
 
  419   : our_data(our_data_in),
 
  420     single_precision(single_precision_in)
 
  424       if (
sizeof(
Real) != 
sizeof(
float))
 
  428   else if (
sizeof(
Real) != 
sizeof(double))
 
  435   if (single_precision)
 
  437       if (
sizeof(
Real) != 
sizeof(
float))
 
  438         return static_cast<void*>(float_vec.data());
 
  441   else if (
sizeof(
Real) != 
sizeof(double))
 
  442     return static_cast<void*>(double_vec.data());
 
  445   return const_cast<void *>(static_cast<const void *>(our_data.data()));
 
  450                   bool single_precision_in)
 
  451   : our_data(our_data_in),
 
  452     single_precision(single_precision_in)
 
  457       if (
sizeof(
Real) != 
sizeof(
float))
 
  460   else if (
sizeof(
Real) != 
sizeof(double))
 
  467   if (single_precision)
 
  469       if (
sizeof(
Real) != 
sizeof(
float))
 
  470         our_data.assign(float_vec.begin(), float_vec.end());
 
  472   else if (
sizeof(
Real) != 
sizeof(double))
 
  473     our_data.assign(double_vec.begin(), double_vec.end());
 
  479   if (single_precision)
 
  481       if (
sizeof(
Real) != 
sizeof(
float))
 
  482         return static_cast<void*>(float_vec.data());
 
  485   else if (
sizeof(
Real) != 
sizeof(double))
 
  486     return static_cast<void*>(double_vec.data());
 
  489   return static_cast<void *>(our_data.data());
 
  495   float ex_version = 0.;
 
  500     comp_ws = cast_int<int>(
sizeof(
float));
 
  505     comp_ws = cast_int<int>(std::min(
sizeof(
Real), 
sizeof(
double)));
 
  512   ex_id = exII::ex_open(filename,
 
  513                         read_only ? EX_READ : EX_WRITE,
 
  518   std::string err_msg = std::string(
"Error opening ExodusII mesh file: ") + std::string(filename);
 
  519   EX_CHECK_ERR(
ex_id, err_msg);
 
  539   exII::ex_init_params params = {};
 
  541   EX_CHECK_ERR(
ex_err, 
"Error retrieving header info.");
 
  545   title.assign(params.title, params.title + MAX_LINE_LENGTH);
 
  558   EX_CHECK_ERR(
ex_err, 
"Error reading number of nodal variables.");
 
  561   EX_CHECK_ERR(
ex_err, 
"Error reading number of elemental variables.");
 
  564   EX_CHECK_ERR(
ex_err, 
"Error reading number of global variables.");
 
  567   EX_CHECK_ERR(
ex_err, 
"Error reading number of sideset variables.");
 
  569   message(
"Exodus header info retrieved successfully.");
 
  579     this->
inquire(exII::EX_INQ_QA, 
"Error retrieving number of QA records");
 
  584                  << 
" QA record(s) in the Exodus file." 
  591       typedef char * inner_array_t[4];
 
  592       inner_array_t * qa_record = 
new inner_array_t[num_qa_rec];
 
  594       for (
int i=0; i<num_qa_rec; i++)
 
  595         for (
int j=0; j<4; j++)
 
  596           qa_record[i][j] = 
new char[MAX_STR_LENGTH+1];
 
  599       EX_CHECK_ERR(
ex_err, 
"Error reading the QA records.");
 
  604           for (
int i=0; i<num_qa_rec; i++)
 
  607               for (
int j=0; j<4; j++)
 
  614       for (
int i=0; i<num_qa_rec; i++)
 
  615         for (
int j=0; j<4; j++)
 
  616           delete [] qa_record[i][j];
 
  629                  << 
"Mesh Dimension: \t"   << 
num_dim << std::endl
 
  630                  << 
"Number of Nodes: \t" << 
num_nodes << std::endl
 
  631                  << 
"Number of elements: \t" << 
num_elem << std::endl
 
  632                  << 
"Number of elt blocks: \t" << 
num_elem_blk << std::endl
 
  647       ex_err = exII::ex_get_coord
 
  653       EX_CHECK_ERR(
ex_err, 
"Error retrieving nodal data.");
 
  654       message(
"Nodal data retrieved successfully.");
 
  668   ex_err = exII::ex_get_node_num_map
 
  671   EX_CHECK_ERR(
ex_err, 
"Error retrieving nodal number map.");
 
  672   message(
"Nodal numbering map retrieved successfully.");
 
  677       for (
unsigned int i=0; i<static_cast<unsigned int>(std::min(10, 
num_nodes-1)); ++i)
 
  687     out_stream << 
"(" << 
x[i] << 
", " << 
y[i] << 
", " << 
z[i] << 
")" << std::endl;
 
  702       EX_CHECK_ERR(
ex_err, 
"Error getting block IDs.");
 
  703       message(
"All block IDs retrieved successfully.");
 
  705       char name_buffer[MAX_STR_LENGTH+1];
 
  708           ex_err = exII::ex_get_name(
ex_id, exII::EX_ELEM_BLOCK,
 
  710           EX_CHECK_ERR(
ex_err, 
"Error getting block name.");
 
  713       message(
"All block names retrieved successfully.");
 
  724       EX_CHECK_ERR(
ex_err, 
"Error getting edge block IDs.");
 
  725       message(
"All edge block IDs retrieved successfully.");
 
  728       char name_buffer[MAX_STR_LENGTH+1];
 
  731           ex_err = exII::ex_get_name(
ex_id, exII::EX_EDGE_BLOCK,
 
  733           EX_CHECK_ERR(
ex_err, 
"Error getting block name.");
 
  736       message(
"All edge block names retrieved successfully.");
 
  744   libmesh_assert_less (index, 
block_ids.size());
 
  753   libmesh_assert_less (index, 
block_ids.size());
 
  762   libmesh_assert_less (index, 
ss_ids.size());
 
  771   libmesh_assert_less (index, 
ss_ids.size());
 
  799   libmesh_assert_less (block, 
block_ids.size());
 
  802   int num_edges_per_elem = 0;
 
  803   int num_faces_per_elem = 0;
 
  814   EX_CHECK_ERR(
ex_err, 
"Error getting block info.");
 
  815   message(
"Info retrieved successfully for block: ", block);
 
  820   if (!(num_edges_per_elem == 0) && !(num_edges_per_elem == -1))
 
  821     libmesh_warning(
"Exodus files with extended edge connectivity not currently supported.");
 
  822   if (!(num_faces_per_elem == 0) && !(num_faces_per_elem == -1))
 
  823     libmesh_warning(
"Exodus files with extended face connectivity not currently supported.");
 
  829                  << 
" nodes per element." << std::endl;
 
  845       EX_CHECK_ERR(
ex_err, 
"Error reading block connectivity.");
 
  846       message(
"Connectivity retrieved successfully for block: ", block);
 
  864   typedef std::pair<dof_id_type, unsigned int> ElemEdgePair;
 
  865   std::unordered_map<dof_id_type, std::vector<ElemEdgePair>> edge_map;
 
  866   for (
const auto & elem : 
mesh.element_ptr_range())
 
  867     for (
auto e : elem->edge_index_range())
 
  873         std::unique_ptr<Elem> edge = elem->build_edge_ptr(e);
 
  877         auto & vec = edge_map[edge_key];
 
  878         vec.push_back(std::make_pair(elem->id(), e));
 
  890       int num_edge_this_blk = 0;
 
  891       int num_nodes_per_edge = 0;
 
  892       int num_edges_per_edge = 0;
 
  893       int num_faces_per_edge = 0;
 
  894       int num_attr_per_edge = 0;
 
  905       EX_CHECK_ERR(
ex_err, 
"Error getting edge block info.");
 
  906       message(
"Info retrieved successfully for block: ", edge_block_id);
 
  911       connect.resize(num_nodes_per_edge * num_edge_this_blk);
 
  922           EX_CHECK_ERR(
ex_err, 
"Error reading block connectivity.");
 
  923           message(
"Connectivity retrieved successfully for block: ", edge_block_id);
 
  932           for (
unsigned int i=0, sz=
connect.size(); i<sz; i+=num_nodes_per_edge)
 
  935               for (
int n=0; n<num_nodes_per_edge; ++n)
 
  937                   int exodus_node_id = 
connect[i+n];
 
  938                   int exodus_node_id_zero_based = exodus_node_id - 1;
 
  939                   int libmesh_node_id = 
node_num_map[exodus_node_id_zero_based] - 1;
 
  941                   edge->set_node(n) = 
mesh.node_ptr(libmesh_node_id);
 
  950               auto & elem_edge_pair_vec =
 
  951                 libmesh_map_find(edge_map, edge_key);
 
  953               for (
const auto & elem_edge_pair : elem_edge_pair_vec)
 
  964                   auto candidate_edge =
 
  965                     mesh.elem_ptr(elem_edge_pair.first)->
 
  966                     build_edge_ptr(elem_edge_pair.second);
 
  970                   bool is_match = 
true;
 
  971                   for (
int n=0; n<num_nodes_per_edge; ++n)
 
  972                     if (candidate_edge->node_id(n) != edge->node_id(n))
 
  982                                   elem_edge_pair.second,
 
 1004   ex_err = exII::ex_get_elem_num_map
 
 1007   EX_CHECK_ERR(
ex_err, 
"Error retrieving element number map.");
 
 1008   message(
"Element numbering map retrieved successfully.");
 
 1014       for (
unsigned int i=0; i<static_cast<unsigned int>(std::min(10, 
num_elem-1)); ++i)
 
 1030       EX_CHECK_ERR(
ex_err, 
"Error retrieving sideset information.");
 
 1031       message(
"All sideset information retrieved successfully.");
 
 1045   char name_buffer[MAX_STR_LENGTH+1];
 
 1048       ex_err = exII::ex_get_name(
ex_id, exII::EX_SIDE_SET,
 
 1050       EX_CHECK_ERR(
ex_err, 
"Error getting side set name.");
 
 1053   message(
"All side set names retrieved successfully.");
 
 1065       EX_CHECK_ERR(
ex_err, 
"Error retrieving nodeset information.");
 
 1066       message(
"All nodeset information retrieved successfully.");
 
 1073   char name_buffer[MAX_STR_LENGTH+1];
 
 1076       ex_err = exII::ex_get_name(
ex_id, exII::EX_NODE_SET,
 
 1078       EX_CHECK_ERR(
ex_err, 
"Error getting node set name.");
 
 1081   message(
"All node set names retrieved successfully.");
 
 1088   libmesh_assert_less (
id, 
ss_ids.size());
 
 1091   libmesh_assert_less_equal (offset, 
elem_list.size());
 
 1092   libmesh_assert_less_equal (offset, 
side_list.size());
 
 1099   EX_CHECK_ERR(
ex_err, 
"Error retrieving sideset parameters.");
 
 1100   message(
"Parameters retrieved successfully for sideset: ", 
id);
 
 1106   if (static_cast<unsigned int>(offset) == 
elem_list.size() ||
 
 1107       static_cast<unsigned int>(offset) == 
side_list.size() )
 
 1121       EX_CHECK_ERR(
ex_err, 
"Error retrieving sideset data.");
 
 1122       message(
"Data retrieved successfully for sideset: ", 
id);
 
 1142   EX_CHECK_ERR(
ex_err, 
"Error retrieving nodeset parameters.");
 
 1143   message(
"Parameters retrieved successfully for nodeset: ", 
id);
 
 1157       EX_CHECK_ERR(
ex_err, 
"Error retrieving nodeset data.");
 
 1158       message(
"Data retrieved successfully for nodeset: ", 
id);
 
 1170     (exII::EX_INQ_NODE_SETS,
 
 1171      "Error retrieving number of node sets");
 
 1174   int total_nodes_in_all_sets =
 
 1176     (exII::EX_INQ_NS_NODE_LEN,
 
 1177      "Error retrieving number of nodes in all node sets.");
 
 1180   int total_df_in_all_sets =
 
 1182     (exII::EX_INQ_NS_DF_LEN,
 
 1183      "Error retrieving number of distribution factors in all node sets.");
 
 1199   ex_err = exII::ex_get_concat_node_sets
 
 1207      total_df_in_all_sets ?
 
 1210   EX_CHECK_ERR(
ex_err, 
"Error reading concatenated nodesets");
 
 1213   char name_buffer[MAX_STR_LENGTH+1];
 
 1216       ex_err = exII::ex_get_name
 
 1221       EX_CHECK_ERR(
ex_err, 
"Error getting node set name.");
 
 1239           EX_CHECK_ERR(
ex_err, 
"Error closing Exodus file.");
 
 1240           message(
"Exodus file closed successfully.");
 
 1251   float ret_float = 0.;
 
 1259   EX_CHECK_ERR(
ex_err, error_msg);
 
 1274       ex_err = exII::ex_get_all_times
 
 1277       EX_CHECK_ERR(
ex_err, 
"Error reading timesteps!");
 
 1286     this->
inquire(exII::EX_INQ_TIME, 
"Error retrieving number of time steps");
 
 1297   unsigned int var_index = 0;
 
 1314       libmesh_error_msg(
"Unable to locate variable named: " << nodal_var_name);
 
 1320   std::vector<Real> unmapped_nodal_var_values(
num_nodes);
 
 1323   ex_err = exII::ex_get_nodal_var
 
 1329   EX_CHECK_ERR(
ex_err, 
"Error reading nodal variable values!");
 
 1331   for (
unsigned i=0; i<static_cast<unsigned>(
num_nodes); i++)
 
 1361       libmesh_error_msg(
"Unrecognized ExodusVarType " << type);
 
 1369                                              std::vector<std::string> & result)
 
 1372   ex_err = exII::ex_get_var_param(
ex_id, var_type, &count);
 
 1373   EX_CHECK_ERR(
ex_err, 
"Error reading number of variables.");
 
 1380   NamesData names_table(count, MAX_STR_LENGTH);
 
 1387   EX_CHECK_ERR(
ex_err, 
"Error reading variable names!");
 
 1391       libMesh::out << 
"Read the variable(s) from the file:" << std::endl;
 
 1392       for (
int i=0; i<count; i++)
 
 1397   result.resize(count);
 
 1400   for (
int i=0; i<count; i++)
 
 1409                                     const std::vector<std::string> & names)
 
 1431       libmesh_error_msg(
"Unrecognized ExodusVarType " << type);
 
 1440                                          const std::vector<std::string> & names)
 
 1443   count = cast_int<int>(names.size());
 
 1446   ex_err = exII::ex_put_var_param(
ex_id, var_type, count);
 
 1447   EX_CHECK_ERR(
ex_err, 
"Error setting number of vars.");
 
 1451       NamesData names_table(count, MAX_STR_LENGTH);
 
 1454       for (
int i=0; i != count; ++i)
 
 1459           libMesh::out << 
"Writing variable name(s) to file: " << std::endl;
 
 1460           for (
int i=0; i != count; ++i)
 
 1470       EX_CHECK_ERR(
ex_err, 
"Error writing variable names.");
 
 1478                                                    std::map<dof_id_type, Real> & elem_var_value_map)
 
 1483   unsigned int var_index = 0;
 
 1500       libmesh_error_msg(
"Unable to locate variable named: " << elemental_var_name);
 
 1504   unsigned ex_el_num = 0;
 
 1510   for (
unsigned i=0; i<static_cast<unsigned>(
num_elem_blk); i++)
 
 1518       EX_CHECK_ERR(
ex_err, 
"Error getting number of elements in block.");
 
 1531       ex_err = exII::ex_get_elem_var
 
 1538       EX_CHECK_ERR(
ex_err, 
"Error getting elemental values.");
 
 1544           unsigned mapped_elem_id = this->
elem_num_map[ex_el_num] - 1;
 
 1547           elem_var_value_map[mapped_elem_id] = block_elem_var_values[j];
 
 1571           comp_ws = cast_int<int>(
sizeof(
float));
 
 1572           io_ws = cast_int<int>(
sizeof(
float));
 
 1578           comp_ws = cast_int<int>
 
 1579             (std::min(
sizeof(
Real), 
sizeof(
double)));
 
 1580           io_ws = cast_int<int>
 
 1581             (std::min(
sizeof(
Real), 
sizeof(
double)));
 
 1587       int mode = EX_CLOBBER;
 
 1592 #ifdef LIBMESH_HAVE_HDF5 
 1594       mode |= EX_NOCLASSIC;
 
 1597       ex_id = exII::ex_create(filename.c_str(), mode, &comp_ws, &io_ws);
 
 1599       EX_CHECK_ERR(
ex_id, 
"Error creating ExodusII mesh file.");
 
 1602         libMesh::out << 
"File created successfully." << std::endl;
 
 1616   unsigned int n_active_elem = 
mesh.n_active_elem();
 
 1633   if (!use_discontinuous)
 
 1642       for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 1646   std::vector<boundary_id_type> unique_side_boundaries;
 
 1647   std::vector<boundary_id_type> unique_node_boundaries;
 
 1653     std::vector<boundary_id_type> shellface_boundaries;
 
 1655     for (
const auto & 
id : shellface_boundaries)
 
 1656       unique_side_boundaries.push_back(
id);
 
 1660   num_side_sets = cast_int<int>(unique_side_boundaries.size());
 
 1661   num_node_sets = cast_int<int>(unique_node_boundaries.size());
 
 1664   std::map<subdomain_id_type, std::vector<unsigned int>> subdomain_map;
 
 1666   for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 1671 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 
 1672       if (elem->infinite())
 
 1677       subdomain_map[cur_subdomain].push_back(elem->id());
 
 1681   if (str_title.size() > MAX_LINE_LENGTH)
 
 1683       libMesh::err << 
"Warning, Exodus files cannot have titles longer than " 
 1685                    << 
" characters.  Your title will be truncated." 
 1687       str_title.resize(MAX_LINE_LENGTH);
 
 1709   exII::ex_init_params params = {};
 
 1710   params.title[str_title.copy(params.title, MAX_LINE_LENGTH)] = 
'\0';
 
 1713   params.num_elem = n_active_elem;
 
 1721   EX_CHECK_ERR(
ex_err, 
"Error initializing new Exodus file.");
 
 1755   if (!use_discontinuous)
 
 1757       for (
const auto & node_ptr : 
mesh.node_ptr_range())
 
 1759           const Node & node = *node_ptr;
 
 1785       for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 1786         for (
const Node & node : elem->node_ref_range())
 
 1788             x.push_back(node(0));
 
 1790             y.push_back(node(1));
 
 1795             z.push_back(node(2));
 
 1809   ex_err = exII::ex_put_coord
 
 1815   EX_CHECK_ERR(
ex_err, 
"Error writing coordinates to Exodus file.");
 
 1817   if (!use_discontinuous)
 
 1821       EX_CHECK_ERR(
ex_err, 
"Error writing node_num_map");
 
 1830   unsigned int n_active_elem = 
mesh.n_active_elem();
 
 1837   typedef std::map<subdomain_id_type, std::vector<dof_id_type>> subdomain_map_type;
 
 1838   subdomain_map_type subdomain_map;
 
 1841   for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 1846 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 
 1847       if (elem->infinite())
 
 1851       subdomain_map[ elem->subdomain_id() ].push_back(elem->id());
 
 1858   std::vector<int>::iterator curr_elem_map_end = 
elem_num_map.begin();
 
 1860   std::vector<int> elem_blk_id;
 
 1861   std::vector<int> num_elem_this_blk_vec;
 
 1862   std::vector<int> num_nodes_per_elem_vec;
 
 1863   std::vector<int> num_edges_per_elem_vec;
 
 1864   std::vector<int> num_faces_per_elem_vec;
 
 1865   std::vector<int> num_attr_vec;
 
 1875   unsigned int counter = 0;
 
 1876   for (
auto & pr : subdomain_map)
 
 1882       subdomain_map_type::mapped_type & tmp_vec = pr.second;
 
 1890       elem_blk_id.push_back(pr.first);
 
 1892       num_elem_this_blk_vec.push_back(cast_int<int>(tmp_vec.size()));
 
 1894       num_attr_vec.push_back(0); 
 
 1895       num_edges_per_elem_vec.push_back(0); 
 
 1896       num_faces_per_elem_vec.push_back(0); 
 
 1906   std::map<std::pair<dof_id_type, unsigned int>, 
dof_id_type> discontinuous_node_indices;
 
 1907   if (use_discontinuous)
 
 1910     for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 1911       for (
auto n : elem->node_index_range())
 
 1913           std::pair<dof_id_type,unsigned int> id_pair;
 
 1914           id_pair.first = elem->id();
 
 1916           discontinuous_node_indices[id_pair] = node_counter;
 
 1925   std::vector<BoundaryInfo::BCTuple> edge_tuples = bi.
build_edge_list();
 
 1933   std::map<boundary_id_type, std::vector<int>> edge_id_to_conn;
 
 1934   std::map<boundary_id_type, std::pair<ElemType, unsigned int>> edge_id_to_elem_type;
 
 1936   for (
const auto & t : edge_tuples)
 
 1939       unsigned int edge_id = std::get<1>(t);
 
 1943       std::unique_ptr<const Elem> edge =
 
 1944         mesh.elem_ptr(elem_id)->build_edge_ptr(edge_id);
 
 1948       auto check_it = edge_id_to_elem_type.find(b_id);
 
 1950       if (check_it == edge_id_to_elem_type.end())
 
 1953           edge_id_to_elem_type[b_id] = std::make_pair(edge->type(), edge->n_nodes());
 
 1958           auto & val_pair = check_it->second;
 
 1959           if (val_pair.first != edge->type() || val_pair.second != edge->n_nodes())
 
 1960             libmesh_error_msg(
"All edges in a block must have same geometric type.");
 
 1964       auto & conn = edge_id_to_conn[b_id];
 
 1970       for (
auto n : edge->node_index_range())
 
 1972           dof_id_type libmesh_node_id = edge->node_ptr(n)->id();
 
 1976           int exodus_node_id = -1;
 
 1978           if (!use_discontinuous)
 
 1979             exodus_node_id = libmesh_map_find
 
 1991               const Elem * parent = 
mesh.elem_ptr(elem_id);
 
 1993                 if (parent->
node_ptr(pn)->
id() == libmesh_node_id)
 
 1995                     exodus_node_id = libmesh_map_find
 
 1996                       (discontinuous_node_indices,
 
 1997                        std::make_pair(elem_id, pn));
 
 2002           if (exodus_node_id == -1)
 
 2003             libmesh_error_msg(
"Unable to map edge's libMesh node id to its Exodus node id.");
 
 2005           conn.push_back(exodus_node_id);
 
 2015   std::vector<int> edge_blk_id;
 
 2017   std::vector<int> num_edge_this_blk_vec;
 
 2018   std::vector<int> num_nodes_per_edge_vec;
 
 2019   std::vector<int> num_attr_edge_vec;
 
 2026   for (
const auto & pr : edge_id_to_conn)
 
 2030       edge_blk_id.push_back(
id);
 
 2033       const auto & elem_type_node_count = edge_id_to_elem_type[id];
 
 2036       num_nodes_per_edge_vec.push_back(elem_type_node_count.second);
 
 2040       num_edge_this_blk_vec.push_back(pr.second.size() / elem_type_node_count.second);
 
 2043       num_attr_edge_vec.push_back(0);
 
 2060   exII::ex_block_params params = {};
 
 2063   params.elem_blk_id = elem_blk_id.data();
 
 2065   params.num_elem_this_blk = num_elem_this_blk_vec.data();
 
 2066   params.num_nodes_per_elem = num_nodes_per_elem_vec.data();
 
 2067   params.num_edges_per_elem = num_edges_per_elem_vec.data();
 
 2068   params.num_faces_per_elem = num_faces_per_elem_vec.data();
 
 2069   params.num_attr_elem = num_attr_vec.data();
 
 2070   params.define_maps = 0;
 
 2075       params.edge_blk_id = edge_blk_id.data();
 
 2077       params.num_edge_this_blk = num_edge_this_blk_vec.data();
 
 2078       params.num_nodes_per_edge = num_nodes_per_edge_vec.data();
 
 2079       params.num_attr_edge = num_attr_edge_vec.data();
 
 2082   ex_err = exII::ex_put_concat_all_blocks(
ex_id, ¶ms);
 
 2083   EX_CHECK_ERR(
ex_err, 
"Error writing element blocks.");
 
 2086   unsigned libmesh_elem_num_to_exodus_counter = 0;
 
 2088   for (
auto & pr : subdomain_map)
 
 2091       subdomain_map_type::mapped_type & tmp_vec = pr.second;
 
 2103           unsigned int elem_id = tmp_vec[i];
 
 2106           const Elem & elem = 
mesh.elem_ref(elem_id);
 
 2118           if (elem.
type() != conv.libmesh_elem_type())
 
 2119             libmesh_error_msg(
"Error: Exodus requires all elements with a given subdomain ID to be the same type.\n" \
 
 2120                               << 
"Can't write both "                  \
 
 2124                               << 
" in the same block!");
 
 2130               unsigned elem_node_index = conv.get_inverse_node_map(j); 
 
 2131               if (!use_discontinuous)
 
 2141                                      cast_int<int>(libmesh_node_id));
 
 2147                     libmesh_map_find(discontinuous_node_indices,
 
 2148                                      std::make_pair(elem_id, elem_node_index));
 
 2153       ex_err = exII::ex_put_conn
 
 2155          exII::EX_ELEM_BLOCK,
 
 2160       EX_CHECK_ERR(
ex_err, 
"Error writing element connectivities");
 
 2167       curr_elem_map_end = std::transform
 
 2176   EX_CHECK_ERR(
ex_err, 
"Error writing element map");
 
 2182       EX_CHECK_ERR(
ex_err, 
"Error writing element block names");
 
 2186   for (
const auto & pr : edge_id_to_conn)
 
 2188       ex_err = exII::ex_put_conn
 
 2190          exII::EX_EDGE_BLOCK,
 
 2195       EX_CHECK_ERR(
ex_err, 
"Error writing element connectivities");
 
 2201       ex_err = exII::ex_put_names
 
 2203          exII::EX_EDGE_BLOCK,
 
 2205       EX_CHECK_ERR(
ex_err, 
"Error writing edge block names");
 
 2218   std::map<int, std::vector<int>> elem;
 
 2219   std::map<int, std::vector<int>> side;
 
 2220   std::vector<boundary_id_type> side_boundary_ids;
 
 2225     for (
const auto & t : 
mesh.get_boundary_info().build_side_list())
 
 2227         std::vector<const Elem *> family;
 
 2228 #ifdef LIBMESH_ENABLE_AMR 
 2233         mesh.elem_ref(std::get<0>(t)).active_family_tree_by_side(family, std::get<1>(t), 
false);
 
 2235         family.push_back(
mesh.elem_ptr(std::get<0>(t)));
 
 2238         for (
const auto & f : family)
 
 2245             side[std::get<2>(t)].push_back(conv.get_inverse_side_map(std::get<1>(t)));
 
 2249     mesh.get_boundary_info().build_side_boundary_ids(side_boundary_ids);
 
 2256     for (
const auto & t : 
mesh.get_boundary_info().build_shellface_list())
 
 2258         std::vector<const Elem *> family;
 
 2259 #ifdef LIBMESH_ENABLE_AMR 
 2264         mesh.elem_ref(std::get<0>(t)).active_family_tree_by_side(family, std::get<1>(t), 
false);
 
 2266         family.push_back(
mesh.elem_ptr(std::get<0>(t)));
 
 2269         for (
const auto & f : family)
 
 2276             side[std::get<2>(t)].push_back(conv.get_inverse_shellface_map(std::get<1>(t)));
 
 2280     std::vector<boundary_id_type> shellface_boundary_ids;
 
 2281     mesh.get_boundary_info().build_shellface_boundary_ids(shellface_boundary_ids);
 
 2282     for (
const auto & 
id : shellface_boundary_ids)
 
 2283       side_boundary_ids.push_back(
id);
 
 2287   if (side_boundary_ids.size() > 0)
 
 2289       NamesData names_table(side_boundary_ids.size(), MAX_STR_LENGTH);
 
 2291       std::vector<exII::ex_set> sets(side_boundary_ids.size());
 
 2299           sets[i].type = exII::EX_SIDE_SET;
 
 2300           sets[i].num_entry = elem[ss_id].size();
 
 2301           sets[i].num_distribution_factor = 0;
 
 2302           sets[i].entry_list = elem[ss_id].data();
 
 2303           sets[i].extra_list = side[ss_id].data();
 
 2304           sets[i].distribution_factor_list = 
nullptr;
 
 2307       ex_err = exII::ex_put_sets(
ex_id, side_boundary_ids.size(), sets.data());
 
 2308       EX_CHECK_ERR(
ex_err, 
"Error writing sidesets");
 
 2310       ex_err = exII::ex_put_names(
ex_id, exII::EX_SIDE_SET, names_table.get_char_star_star());
 
 2311       EX_CHECK_ERR(
ex_err, 
"Error writing sideset names");
 
 2325   typedef std::tuple<dof_id_type, boundary_id_type> tuple_t;
 
 2326   std::vector<tuple_t> bc_tuples =
 
 2327     mesh.get_boundary_info().build_node_list();
 
 2331   std::stable_sort(bc_tuples.begin(), bc_tuples.end(),
 
 2332                    [](
const tuple_t & t1,
 
 2334                    { 
return std::get<1>(t1) < std::get<1>(t2); });
 
 2336   std::vector<boundary_id_type> node_boundary_ids;
 
 2337   mesh.get_boundary_info().build_node_boundary_ids(node_boundary_ids);
 
 2340   if (node_boundary_ids.size() > 0 &&
 
 2341       bc_tuples.size() > 0)
 
 2343       NamesData names_table(node_boundary_ids.size(), MAX_STR_LENGTH);
 
 2361       std::map<boundary_id_type, unsigned int> nodeset_counts;
 
 2362       for (
const auto & t : bc_tuples)
 
 2367           nodeset_counts[nodeset_id] += 1;
 
 2371       unsigned int running_sum = 0;
 
 2372       for (
const auto & pr : nodeset_counts)
 
 2377           names_table.push_back_entry(
mesh.get_boundary_info().get_nodeset_name(pr.first));
 
 2378           running_sum += pr.second;
 
 2383       exII::ex_set_specs set_data = {};
 
 2392       ex_err = exII::ex_put_concat_sets(
ex_id, exII::EX_NODE_SET, &set_data);
 
 2393       EX_CHECK_ERR(
ex_err, 
"Error writing concatenated nodesets");
 
 2396       ex_err = exII::ex_put_names(
ex_id, exII::EX_NODE_SET, names_table.get_char_star_star());
 
 2397       EX_CHECK_ERR(
ex_err, 
"Error writing nodeset names");
 
 2404                                                       const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
 
 2410   if (names.size() == 0)
 
 2433   for (
auto var_num : 
index_range(vars_active_subdomains))
 
 2437       std::set<subdomain_id_type> current_set;
 
 2438       if (vars_active_subdomains[var_num].empty())
 
 2440           current_set.insert(cast_int<subdomain_id_type>(block_id));
 
 2442         current_set = vars_active_subdomains[var_num];
 
 2445       for (
auto block_id : current_set)
 
 2449             libmesh_error_msg(
"ExodusII_IO_Helper: block id " << block_id << 
" not found in block_ids.");
 
 2451           std::size_t block_index =
 
 2454           std::size_t truth_tab_index = block_index*
num_elem_vars + var_num;
 
 2455           truth_tab[truth_tab_index] = 1;
 
 2463   EX_CHECK_ERR(
ex_err, 
"Error writing element truth table.");
 
 2474   if (names.size() == 0)
 
 2502   if (names.size() == 0)
 
 2523                                              std::vector<std::string> & names,
 
 2524                                              std::vector<std::string> & names_from_file)
 
 2539                names_from_file.begin(),
 
 2540                [](
const std::string & a,
 
 2541                   const std::string & b) -> 
bool 
 2543                  return a.compare(0, MAX_STR_LENGTH, b) == 0;
 
 2548       libMesh::err << 
"Error! The Exodus file already contains the variables:" << std::endl;
 
 2549       for (
const auto & 
name : names_from_file)
 
 2552       libMesh::err << 
"And you asked to write:" << std::endl;
 
 2553       for (
const auto & 
name : names)
 
 2556       libmesh_error_msg(
"Cannot overwrite existing variables in Exodus II file.");
 
 2569       float cast_time = float(time);
 
 2570       ex_err = exII::ex_put_time(
ex_id, timestep, &cast_time);
 
 2574       double cast_time = double(time);
 
 2575       ex_err = exII::ex_put_time(
ex_id, timestep, &cast_time);
 
 2577   EX_CHECK_ERR(
ex_err, 
"Error writing timestep.");
 
 2580   EX_CHECK_ERR(
ex_err, 
"Error flushing buffers to file.");
 
 2589                    const std::vector<std::string> & var_names,
 
 2590                    const std::vector<std::set<boundary_id_type>> & side_ids,
 
 2591                    const std::vector<std::map<BoundaryInfo::BCTuple, Real>> & bc_vals)
 
 2620   std::vector<int> sset_var_tab(
num_side_sets * var_names.size());
 
 2645           if (!side_ids[var].count(
ss_ids[ss]))
 
 2649           sset_var_tab[ss*var_names.size() + var] = 1;
 
 2655           const auto & data_map = bc_vals[var];
 
 2674               unsigned int side_id = 
side_list[i + offset] - 1;
 
 2680                 libmesh_error_msg(
"Error mapping Exodus elem id to libmesh elem id.");
 
 2686               unsigned int converted_side_id = conv.
get_side_map(side_id);
 
 2703               sset_var_vals[i] = libmesh_map_find(data_map, key);
 
 2709           if (sset_var_vals.size() > 0)
 
 2711               ex_err = exII::ex_put_sset_var
 
 2718               EX_CHECK_ERR(
ex_err, 
"Error writing sideset vars.");
 
 2725     exII::ex_put_sset_var_tab(
ex_id,
 
 2727                               cast_int<int>(var_names.size()),
 
 2728                               sset_var_tab.data());
 
 2729   EX_CHECK_ERR(
ex_err, 
"Error writing sideset var truth table.");
 
 2738                   std::vector<std::string> & var_names,
 
 2739                   std::vector<std::set<boundary_id_type>> & side_ids,
 
 2740                   std::vector<std::map<BoundaryInfo::BCTuple, Real>> & bc_vals)
 
 2750       ex_err = exII::ex_get_sset_var_tab
 
 2754          sset_var_tab.data());
 
 2755       EX_CHECK_ERR(
ex_err, 
"Error reading sideset variable truth table.");
 
 2784                   side_ids[var].insert(
ss_ids[ss]);
 
 2790                   ex_err = exII::ex_get_sset_var
 
 2797                   EX_CHECK_ERR(
ex_err, 
"Error reading sideset variable.");
 
 2810                       unsigned int exodus_side_id = 
side_list[i + offset];
 
 2815                       dof_id_type converted_elem_id = exodus_elem_id - 1;
 
 2824                       unsigned int converted_side_id = conv.
get_side_map(exodus_side_id - 1);
 
 2843                       bc_vals[var].insert(std::make_pair(key, sset_var_vals[i]));
 
 2855  const std::vector<Real> & values,
 
 2857  const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
 
 2864   EX_CHECK_ERR(
ex_err, 
"Error reading number of elemental variables.");
 
 2869   std::map<subdomain_id_type, std::vector<unsigned int>> subdomain_map;
 
 2870   for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 2871     subdomain_map[elem->subdomain_id()].push_back(elem->id());
 
 2880   libmesh_assert_equal_to
 
 2881     (vars_active_subdomains.size(),
 
 2887   for (
unsigned int var_id=0; var_id<static_cast<unsigned>(
num_elem_vars); ++var_id)
 
 2890       auto it = subdomain_map.begin();
 
 2893       const auto & active_subdomains
 
 2894         = vars_active_subdomains[var_id];
 
 2896       for (
unsigned int j=0; it!=subdomain_map.end(); ++it, ++j)
 
 2901           if (!(active_subdomains.empty() || active_subdomains.count(it->first)))
 
 2907           const auto & elem_nums = it->second;
 
 2908           const unsigned int num_elems_this_block =
 
 2909             cast_int<unsigned int>(elem_nums.size());
 
 2910           std::vector<Real> 
data(num_elems_this_block);
 
 2915           for (
unsigned int k=0; k<num_elems_this_block; ++k)
 
 2916             data[k] = values[var_id*
n_elem + elem_nums[k]];
 
 2918           ex_err = exII::ex_put_elem_var
 
 2923              num_elems_this_block,
 
 2926           EX_CHECK_ERR(
ex_err, 
"Error writing element values.");
 
 2931   EX_CHECK_ERR(
ex_err, 
"Error flushing buffers to file.");
 
 2938  const std::vector<Real> & values,
 
 2940  const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains,
 
 2941  const std::vector<std::string> & derived_var_names,
 
 2942  const std::map<
subdomain_id_type, std::vector<std::string>> & subdomain_to_var_names)
 
 2949   EX_CHECK_ERR(
ex_err, 
"Error reading number of elemental variables.");
 
 2956   std::map<subdomain_id_type, unsigned int> subdomain_to_n_elem;
 
 2957   for (
const auto & elem : 
mesh.active_element_ptr_range())
 
 2958     subdomain_to_n_elem[elem->subdomain_id()] += 1;
 
 2962   libmesh_assert_equal_to
 
 2963     (vars_active_subdomains.size(),
 
 2967   auto subdomain_to_n_elem_iter = subdomain_to_n_elem.begin();
 
 2973     (
mesh.active_elements_begin(),
 
 2974      mesh.active_elements_end());
 
 2976   for (
unsigned int sbd_idx=0;
 
 2977        subdomain_to_n_elem_iter != subdomain_to_n_elem.end();
 
 2978        ++subdomain_to_n_elem_iter, ++sbd_idx)
 
 2979     for (
unsigned int var_id=0; var_id<static_cast<unsigned>(
num_elem_vars); ++var_id)
 
 2982         const auto & active_subdomains
 
 2983           = vars_active_subdomains[var_id];
 
 2990         if (!active_subdomains.count(subdomain_to_n_elem_iter->first))
 
 2994         std::vector<Real> 
data;
 
 2995         data.reserve(subdomain_to_n_elem_iter->second);
 
 2997         unsigned int values_offset = 0;
 
 2998         for (
auto & elem : elem_range)
 
 3005             auto subdomain_to_var_names_iter =
 
 3006               subdomain_to_var_names.find(sbd_id);
 
 3014             if (subdomain_to_var_names_iter == subdomain_to_var_names.end())
 
 3017             const auto & var_names_this_sbd
 
 3018               = subdomain_to_var_names_iter->second;
 
 3021             if (sbd_id == subdomain_to_n_elem_iter->first)
 
 3029                   std::find(var_names_this_sbd.begin(),
 
 3030                             var_names_this_sbd.end(),
 
 3031                             derived_var_names[var_id]);
 
 3033                 if (pos == var_names_this_sbd.end())
 
 3034                   libmesh_error_msg(
"Derived name " << derived_var_names[var_id] << 
" not found!");
 
 3041                 data.push_back(values[values_offset + true_index]);
 
 3046             auto true_offset = var_names_this_sbd.size();
 
 3049             values_offset += true_offset;
 
 3055             ex_err = exII::ex_put_elem_var
 
 3059             EX_CHECK_ERR(
ex_err, 
"Error writing element values.");
 
 3064   EX_CHECK_ERR(
ex_err, 
"Error flushing buffers to file.");
 
 3071                                        const std::vector<Real> & values,
 
 3077   if (!values.empty())
 
 3079       ex_err = exII::ex_put_nodal_var
 
 3083       EX_CHECK_ERR(
ex_err, 
"Error writing nodal values.");
 
 3086       EX_CHECK_ERR(
ex_err, 
"Error flushing buffers to file.");
 
 3101   int num_info = 
inquire(exII::EX_INQ_INFO, 
"Error retrieving the number of information records from file!");
 
 3104       libMesh::err << 
"Warning! The Exodus file already contains information records.\n" 
 3105                    << 
"Exodus does not support writing additional records in this situation." 
 3110   int num_records = cast_int<int>(records.size());
 
 3112   if (num_records > 0)
 
 3114       NamesData info(num_records, MAX_LINE_LENGTH);
 
 3118       for (
const auto & record : records)
 
 3122       EX_CHECK_ERR(
ex_err, 
"Error writing global values.");
 
 3125       EX_CHECK_ERR(
ex_err, 
"Error flushing buffers to file.");
 
 3136   if (!values.empty())
 
 3138       ex_err = exII::ex_put_glob_vars
 
 3142       EX_CHECK_ERR(
ex_err, 
"Error writing global values.");
 
 3145       EX_CHECK_ERR(
ex_err, 
"Error flushing buffers to file.");
 
 3158   ex_err = exII::ex_get_glob_vars
 
 3162   EX_CHECK_ERR(
ex_err, 
"Error reading global values.");
 
 3187 std::vector<std::string>
 
 3190   std::vector<std::string> complex_names;
 
 3194   for (
const auto & 
name : names)
 
 3196       complex_names.push_back(
"r_" + 
name);
 
 3197       complex_names.push_back(
"i_" + 
name);
 
 3198       complex_names.push_back(
"a_" + 
name);
 
 3201   return complex_names;
 
 3207   const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
 const 
 3209   std::vector<std::set<subdomain_id_type>> complex_vars_active_subdomains;
 
 3211   for (
auto & s : vars_active_subdomains)
 
 3215       complex_vars_active_subdomains.push_back(s);
 
 3216       complex_vars_active_subdomains.push_back(s);
 
 3217       complex_vars_active_subdomains.push_back(s);
 
 3220   return complex_vars_active_subdomains;
 
 3225 std::map<subdomain_id_type, std::vector<std::string>>
 
 3228   const std::map<
subdomain_id_type, std::vector<std::string>> & subdomain_to_var_names)
 const 
 3231   std::map<subdomain_id_type, std::vector<std::string>> ret;
 
 3233   for (
const auto & pr : subdomain_to_var_names)
 
 3236       auto & vec = ret[pr.first];
 
 3239       const auto & varnames = pr.second;
 
 3242       vec.reserve(3 * varnames.size());
 
 3247       for (
const auto & varname : varnames)
 
 3249           vec.push_back(
"r_" + varname);
 
 3250           vec.push_back(
"i_" + varname);
 
 3251           vec.push_back(
"a_" + varname);
 
 3264   libmesh_assert_less (i, node_map->size());
 
 3265   return (*node_map)[i];
 
 3272   if (!inverse_node_map)
 
 3275   libmesh_assert_less (i, inverse_node_map->size());
 
 3276   return (*inverse_node_map)[i];
 
 3288   if (static_cast<size_t>(i) >= side_map->size())
 
 3291   return (*side_map)[i];
 
 3299   if (!inverse_side_map)
 
 3302   libmesh_assert_less (i, inverse_side_map->size());
 
 3303   return (*inverse_side_map)[i];
 
 3317   libmesh_assert_less (i, shellface_map->size());
 
 3318   return (*shellface_map)[i];
 
 3325   if (!inverse_shellface_map)
 
 3328   libmesh_assert_less (i, inverse_shellface_map->size());
 
 3329   return (*inverse_shellface_map)[i];
 
 3336   return libmesh_type;
 
 3353   return shellface_index_offset;
 
 3357   data_table(n_strings),
 
 3358   data_table_pointers(n_strings),
 
 3360   table_size(n_strings)
 
 3362   for (
size_t i=0; i<n_strings; ++i)
 
 3378   libmesh_assert_less (counter, table_size);
 
 3381   size_t num_copied = 
name.copy(data_table[counter].
data(), data_table[counter].size()-1);
 
 3384   data_table[counter][num_copied] = 
'\0';
 
 3394   return data_table_pointers.data();
 
 3401   if (static_cast<unsigned>(i) >= table_size)
 
 3402     libmesh_error_msg(
"Requested char * " << i << 
" but only have " << table_size << 
"!");
 
 3405     return data_table[i].data();
 
 3413 #endif // #ifdef LIBMESH_HAVE_EXODUS_API