libMesh
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
libMesh::ExodusII_IO_Helper Class Reference

This is the ExodusII_IO_Helper class. More...

#include <exodusII_io_helper.h>

Inheritance diagram for libMesh::ExodusII_IO_Helper:
[legend]

Classes

class  Conversion
 
struct  MappedInputVector
 This class facilitates reading in vectors from Exodus file that may be of a different floating point type than Real. More...
 
struct  MappedOutputVector
 This class facilitates inline conversion of an input data vector to a different precision level, depending on the underlying type of Real and whether or not the single_precision flag is set. More...
 
class  NamesData
 This class is useful for managing anything that requires a char ** input/output in ExodusII file. More...
 

Public Types

enum  ExodusVarType {
  NODAL =0 , ELEMENTAL =1 , GLOBAL =2 , SIDESET =3 ,
  NODESET =4 , ELEMSET =5
}
 Wraps calls to exII::ex_get_var_names() and exII::ex_get_var_param(). More...
 

Public Member Functions

 ExodusII_IO_Helper (const ParallelObject &parent, bool v=false, bool run_only_on_proc0=true, bool single_precision=false)
 Constructor.
 
 ExodusII_IO_Helper (const ExodusII_IO_Helper &)=default
 Special functions.
 
 ExodusII_IO_Helper (ExodusII_IO_Helper &&)=default
 
virtual ~ExodusII_IO_Helper ()
 
ExodusII_IO_Helper & operator= (const ExodusII_IO_Helper &)=delete
 This class contains references so it can't be default copy/move-assigned.
 
ExodusII_IO_Helper & operator= (ExodusII_IO_Helper &&)=delete
 
const char * get_elem_type () const
 
void set_add_sides (bool add_sides)
 Sets whether or not to write extra "side" elements.
 
bool get_add_sides ()
 
void open (const char *filename, bool read_only)
 Opens an ExodusII mesh file named filename.
 
ExodusHeaderInfo read_header () const
 Reads an ExodusII mesh file header, leaving this object's internal data structures unchanged.
 
void read_and_store_header_info ()
 Reads an ExodusII mesh file header, and stores required information on this object.
 
void read_qa_records ()
 Reads the QA records from an ExodusII file.
 
void print_header ()
 Prints the ExodusII mesh file header, which includes the mesh title, the number of nodes, number of elements, mesh dimension, number of sidesets, and number of nodesets.
 
void read_nodes ()
 Reads the nodal data (x,y,z coordinates) from the ExodusII mesh file.
 
void read_node_num_map ()
 Reads the optional node_num_map from the ExodusII mesh file.
 
void read_bex_cv_blocks ()
 Reads the optional bex_cv_blocks from the ExodusII mesh file.
 
void print_nodes (std::ostream &out_stream=libMesh::out)
 Prints the nodal information, by default to libMesh::out.
 
void read_block_info ()
 Reads information for all of the blocks in the ExodusII mesh file.
 
int get_block_id (int index)
 Get the block number for the given block index.
 
std::string get_block_name (int index)
 Get the block name for the given block index if supplied in the mesh file.
 
int get_side_set_id (int index)
 Get the side set id for the given side set index.
 
std::string get_side_set_name (int index)
 Get the side set name for the given side set index if supplied in the mesh file.
 
int get_node_set_id (int index)
 Get the node set id for the given node set index.
 
std::string get_node_set_name (int index)
 Get the node set name for the given node set index if supplied in the mesh file.
 
void read_elem_in_block (int block)
 Reads all of the element connectivity for block block in the ExodusII mesh file.
 
void read_face_blocks ()
 Reads NSIDED face blocks used by NFACED element blocks.
 
void read_edge_blocks (MeshBase &mesh)
 Read in edge blocks, storing information in the BoundaryInfo object.
 
void read_elem_num_map ()
 Reads the optional node_num_map from the ExodusII mesh file.
 
void read_sideset_info ()
 Reads information about all of the sidesets in the ExodusII mesh file.
 
void read_nodeset_info ()
 Reads information about all of the nodesets in the ExodusII mesh file.
 
void read_elemset_info ()
 Reads information about all of the elemsets in the ExodusII mesh file.
 
void read_sideset (int id, int offset)
 Reads information about sideset id and inserts it into the global sideset array at the position offset.
 
void read_elemset (int id, int offset)
 Reads information about elemset id and inserts it into the global elemset array at the position offset.
 
void read_all_nodesets ()
 New API that reads all nodesets simultaneously.
 
void close () noexcept
 Closes the ExodusII mesh file.
 
void read_time_steps ()
 Reads and stores the timesteps in the 'time_steps' array.
 
void read_num_time_steps ()
 Reads the number of timesteps currently stored in the Exodus file and stores it in the num_time_steps variable.
 
void read_nodal_var_values (std::string nodal_var_name, int time_step)
 Reads the nodal values for the variable 'nodal_var_name' at the specified time into the 'nodal_var_values' array.
 
void read_elemental_var_values (std::string elemental_var_name, int time_step, std::map< dof_id_type, Real > &elem_var_value_map)
 Reads elemental values for the variable 'elemental_var_name' at the specified timestep into the 'elem_var_value_map' which is passed in.
 
dof_id_type get_libmesh_node_id (int exodus_node_id)
 Helper function that takes a (1-based) Exodus node/elem id and determines the corresponding libMesh Node/Elem id.
 
dof_id_type get_libmesh_elem_id (int exodus_elem_id)
 
void conditionally_set_node_unique_id (MeshBase &mesh, Node *node, int zero_based_node_num_map_index)
 Helper function that conditionally sets the unique_id of the passed-in Node/Elem.
 
void conditionally_set_elem_unique_id (MeshBase &mesh, Elem *elem, int zero_based_elem_num_map_index)
 
virtual void create (std::string filename)
 Opens an ExodusII mesh file named filename for writing.
 
virtual void initialize (std::string title, const MeshBase &mesh, bool use_discontinuous=false)
 Initializes the Exodus file.
 
virtual void write_nodal_coordinates (const MeshBase &mesh, bool use_discontinuous=false)
 Writes the nodal coordinates contained in "mesh".
 
virtual void write_elements (const MeshBase &mesh, bool use_discontinuous=false)
 Writes the elements contained in "mesh".
 
virtual void write_sidesets (const MeshBase &mesh)
 Writes the sidesets contained in "mesh".
 
virtual void write_nodesets (const MeshBase &mesh)
 Writes the nodesets contained in "mesh".
 
virtual void initialize_element_variables (std::vector< std::string > names, const std::vector< std::set< subdomain_id_type > > &vars_active_subdomains)
 Sets up the nodal variables.
 
void initialize_nodal_variables (std::vector< std::string > names)
 Sets up the nodal variables.
 
void initialize_global_variables (std::vector< std::string > names)
 Sets up the global variables.
 
void write_timestep (int timestep, Real time)
 Writes the time for the timestep.
 
void write_elemsets (const MeshBase &mesh)
 Write elemsets stored on the Mesh to the exo file.
 
void write_sideset_data (const MeshBase &mesh, int timestep, const std::vector< std::string > &var_names, const std::vector< std::set< boundary_id_type > > &side_ids, const std::vector< std::map< BoundaryInfo::BCTuple, Real > > &bc_vals)
 Write sideset data for the requested timestep.
 
void read_sideset_data (const MeshBase &mesh, int timestep, std::vector< std::string > &var_names, std::vector< std::set< boundary_id_type > > &side_ids, std::vector< std::map< BoundaryInfo::BCTuple, Real > > &bc_vals)
 Read sideset variables, if any, into the provided data structures.
 
void get_sideset_data_indices (const MeshBase &mesh, std::map< BoundaryInfo::BCTuple, unsigned int > &bc_array_indices)
 Similar to read_sideset_data(), but instead of creating one std::map per sideset per variable, creates a single map of (elem, side, boundary_id) tuples, and stores the exo file array indexing for any/all sideset variables on that sideset (they are all the same).
 
void write_nodeset_data (int timestep, const std::vector< std::string > &var_names, const std::vector< std::set< boundary_id_type > > &node_boundary_ids, const std::vector< std::map< BoundaryInfo::NodeBCTuple, Real > > &bc_vals)
 Write nodeset data for the requested timestep.
 
void read_nodeset_data (int timestep, std::vector< std::string > &var_names, std::vector< std::set< boundary_id_type > > &node_boundary_ids, std::vector< std::map< BoundaryInfo::NodeBCTuple, Real > > &bc_vals)
 Read nodeset variables, if any, into the provided data structures.
 
void get_nodeset_data_indices (std::map< BoundaryInfo::NodeBCTuple, unsigned int > &bc_array_indices)
 Similar to read_nodeset_data(), but instead of creating one std::map per nodeset per variable, creates a single map of (node_id, boundary_id) tuples, and stores the exo file array indexing for any/all nodeset variables on that nodeset (they are all the same).
 
void write_elemset_data (int timestep, const std::vector< std::string > &var_names, const std::vector< std::set< elemset_id_type > > &elemset_ids_in, const std::vector< std::map< std::pair< dof_id_type, elemset_id_type >, Real > > &elemset_vals)
 Write elemset data for the requested timestep.
 
void read_elemset_data (int timestep, std::vector< std::string > &var_names, std::vector< std::set< elemset_id_type > > &elemset_ids_in, std::vector< std::map< std::pair< dof_id_type, elemset_id_type >, Real > > &elemset_vals)
 Read elemset variables, if any, into the provided data structures.
 
void get_elemset_data_indices (std::map< std::pair< dof_id_type, elemset_id_type >, unsigned int > &elemset_array_indices)
 Similar to read_elemset_data(), but instead of creating one std::map per elemset per variable, creates a single map of (elem_id, elemset_id) tuples, and stores the exo file array indexing for any/all elemset variables on that elemset (they are all the same).
 
void write_element_values (const MeshBase &mesh, const std::vector< Real > &values, int timestep, const std::vector< std::set< subdomain_id_type > > &vars_active_subdomains)
 Writes the vector of values to the element variables.
 
void write_element_values_element_major (const MeshBase &mesh, const std::vector< Real > &values, int timestep, const std::vector< std::set< subdomain_id_type > > &vars_active_subdomains, const std::vector< std::string > &derived_var_names, const std::map< subdomain_id_type, std::vector< std::string > > &subdomain_to_var_names)
 Same as the function above, but assume the input 'values' vector is in element-major order, i.e.
 
void write_nodal_values (int var_id, const std::vector< Real > &values, int timestep)
 Writes the vector of values to a nodal variable.
 
void write_information_records (const std::vector< std::string > &records)
 Writes the vector of information records.
 
void write_global_values (const std::vector< Real > &values, int timestep)
 Writes the vector of global variables.
 
void update ()
 Uses ex_update() to flush buffers to file.
 
void read_global_values (std::vector< Real > &values, int timestep)
 Reads the vector of global variables.
 
void use_mesh_dimension_instead_of_spatial_dimension (bool val)
 Sets the underlying value of the boolean flag _use_mesh_dimension_instead_of_spatial_dimension.
 
void set_hdf5_writing (bool write_hdf5)
 Set to true (the default) to write files in an HDF5-based file format (when HDF5 is available), or to false to write files in the old NetCDF3-based format.
 
void write_as_dimension (unsigned dim)
 Sets the value of _write_as_dimension.
 
void set_coordinate_offset (Point p)
 Allows you to set a vector that is added to the coordinates of all of the nodes.
 
void set_max_name_length (unsigned int max_length)
 Set how many characters to use in names when opening a file for writing.
 
std::vector< std::string > get_complex_names (const std::vector< std::string > &names, bool write_complex_abs) const
 
std::vector< std::set< subdomain_id_type > > get_complex_vars_active_subdomains (const std::vector< std::set< subdomain_id_type > > &vars_active_subdomains, bool write_complex_abs) const
 returns a "tripled" copy of vars_active_subdomains, which is necessary in the complex-valued case.
 
std::map< subdomain_id_type, std::vector< std::string > > get_complex_subdomain_to_var_names (const std::map< subdomain_id_type, std::vector< std::string > > &subdomain_to_var_names, bool write_complex_abs) const
 Takes a map from subdomain id -> vector of active variable names as input and returns a corresponding map where the original variable names have been replaced by their complex counterparts.
 
void message (std::string_view msg)
 Prints the message defined in msg.
 
void message (std::string_view msg, int i)
 Prints the message defined in msg, and appends the number i to the end of the message.
 
int end_elem_id () const
 
void read_var_names (ExodusVarType type)
 
const ExodusII_IO_Helper::Conversion & get_conversion (const ElemType type) const
 
const ExodusII_IO_Helper::Conversion & get_conversion (std::string type_str) const
 
dof_id_type node_id_to_vec_id (dof_id_type n) const
 
dof_id_type added_node_offset_on (processor_id_type p) const
 
const Parallel::Communicator & comm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Static Public Member Functions

static int get_exodus_version ()
 

Public Attributes

int ex_id
 
int ex_err
 
ExodusHeaderInfo header_info
 
std::vector< char > & title
 
int & num_dim
 
int & num_nodes
 
int & num_elem
 
int & num_elem_blk
 
int & num_edge
 
int & num_edge_blk
 
int & num_face
 
int & num_face_blk
 
int & num_node_sets
 
int & num_side_sets
 
int & num_elem_sets
 
int num_global_vars
 
int num_sideset_vars
 
int num_nodeset_vars
 
int num_elemset_vars
 
int num_elem_this_blk
 
int num_nodes_per_elem
 
int num_attr
 
int num_elem_all_sidesets
 
int num_elem_all_elemsets
 
std::vector< int > block_ids
 
std::vector< int > edge_block_ids
 
std::vector< int > connect
 
std::vector< int > elem_node_counts
 
std::vector< int > elem_face_counts
 
std::vector< std::vector< int > > c0polyhedron_face_connect
 
std::vector< int > ss_ids
 
std::vector< int > nodeset_ids
 
std::vector< int > elemset_ids
 
std::vector< int > num_sides_per_set
 
std::vector< int > num_nodes_per_set
 
std::vector< int > num_elems_per_set
 
std::vector< int > num_df_per_set
 
std::vector< int > num_node_df_per_set
 
std::vector< int > num_elem_df_per_set
 
std::vector< int > node_sets_node_index
 
std::vector< int > node_sets_dist_index
 
std::vector< int > node_sets_node_list
 
std::vector< Real > node_sets_dist_fact
 
std::vector< int > elem_list
 
std::vector< int > side_list
 
std::vector< int > id_list
 
std::vector< int > elemset_list
 
std::vector< int > elemset_id_list
 
std::vector< int > node_num_map
 
std::vector< int > elem_num_map
 
std::vector< Real > x
 
std::vector< Real > y
 
std::vector< Real > z
 
std::vector< Real > w
 
unsigned int bex_num_elem_cvs
 
std::vector< std::vector< long unsigned int > > bex_cv_conn
 
std::vector< std::vector< std::vector< Real > > > bex_dense_constraint_vecs
 
std::vector< char > elem_type
 
std::map< dof_id_type, dof_id_type > libmesh_elem_num_to_exodus
 
std::vector< int > exodus_elem_num_to_libmesh
 
std::map< dof_id_type, dof_id_type > libmesh_node_num_to_exodus
 
std::vector< int > exodus_node_num_to_libmesh
 
int num_time_steps
 
std::vector< Real > time_steps
 
int num_nodal_vars
 
std::vector< std::string > nodal_var_names
 
std::map< dof_id_type, Real > nodal_var_values
 
int num_elem_vars
 
std::vector< std::string > elem_var_names
 
std::vector< Real > elem_var_values
 
std::vector< std::string > global_var_names
 
std::vector< std::string > sideset_var_names
 
std::vector< std::string > nodeset_var_names
 
std::vector< std::string > elemset_var_names
 
std::map< int, std::string > id_to_block_names
 
std::map< int, std::string > id_to_edge_block_names
 
std::map< int, std::string > id_to_ss_names
 
std::map< int, std::string > id_to_ns_names
 
std::map< int, std::string > id_to_elemset_names
 
bool verbose
 
bool set_unique_ids_from_maps
 
bool opened_for_writing
 
bool opened_for_reading
 
std::string current_filename
 

Protected Member Functions

void check_existing_vars (ExodusVarType type, std::vector< std::string > &names, std::vector< std::string > &names_from_file)
 When appending: during initialization, check that variable names in the file match those you attempt to initialize with.
 
void write_var_names (ExodusVarType type, const std::vector< std::string > &names)
 Wraps calls to exII::ex_put_var_names() and exII::ex_put_var_param().
 
virtual void read_var_names_impl (const char *var_type, int &count, std::vector< std::string > &result)
 read_var_names() dispatches to this function.
 

Protected Attributes

bool _run_only_on_proc0
 
bool _opened_by_create
 
bool _elem_vars_initialized
 
bool _global_vars_initialized
 
bool _nodal_vars_initialized
 
bool _use_mesh_dimension_instead_of_spatial_dimension
 
bool _write_hdf5
 
unsigned int _max_name_length
 
int _end_elem_id
 
unsigned _write_as_dimension
 
Point _coordinate_offset
 
bool _single_precision
 
std::vector< dof_id_type > _added_side_node_offsets
 If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS variables, _added_side_node_offsets[p] gives us the total solution vector offset to use on processor p+1 from the nodes on those previous ranks' sides.
 
std::vector< dof_id_type > _true_node_offsets
 If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS variables, we also need to know how many real nodes from previous ranks are taking up space in a solution vector.
 
const Parallel::Communicator & _communicator
 

Private Member Functions

dof_id_type get_libmesh_id (int exodus_id, const std::vector< int > &num_map)
 Internal implementation for the two sets of functions above.
 
void set_dof_object_unique_id (MeshBase &mesh, DofObject *dof_object, int exodus_mapped_id)
 
void write_var_names_impl (const char *var_type, int &count, const std::vector< std::string > &names)
 write_var_names() dispatches to this function.
 
void init_element_equivalence_map ()
 
void init_conversion_map ()
 

Private Attributes

bool _add_sides = false
 Set to true iff we want to write separate "side" elements too.
 
std::map< std::string, ElemType > element_equivalence_map
 Defines equivalence classes of Exodus element types that map to libmesh ElemTypes.
 
std::map< int, std::map< ElemType, ExodusII_IO_Helper::Conversion > > conversion_map
 Associates libMesh ElemTypes with node/face/edge/etc.
 

Detailed Description

This is the ExodusII_IO_Helper class.

This class hides the implementation details of interfacing with the Exodus binary format.

Author
John W. Peterson
Date
2002

Definition at line 74 of file exodusII_io_helper.h.

Member Enumeration Documentation

◆ ExodusVarType

Wraps calls to exII::ex_get_var_names() and exII::ex_get_var_param().

The enumeration controls whether nodal, elemental, global, etc. variable names are read and which class members are filled in. NODAL: num_nodal_vars nodal_var_names ELEMENTAL: num_elem_vars elem_var_names GLOBAL: num_global_vars global_var_names SIDESET: num_sideset_vars sideset_var_names NODESET: num_nodeset_vars nodeset_var_names

Enumerator
NODAL 
ELEMENTAL 
GLOBAL 
SIDESET 
NODESET 
ELEMSET 

Definition at line 951 of file exodusII_io_helper.h.

Constructor & Destructor Documentation

◆ ExodusII_IO_Helper() [1/3]

libMesh::ExodusII_IO_Helper::ExodusII_IO_Helper ( const ParallelObject &  parent,
bool  v = false,
bool  run_only_on_proc0 = true,
bool  single_precision = false 
)

Constructor.

Automatically initializes all the private members of the class. Also allows you to set the verbosity level to v=true (on) or v=false (off). The second argument, if true, tells the class to only perform its actions if running on processor zero. If you initialize this to false, the writing methods will run on all processors instead.

Definition at line 359 of file exodusII_io_helper.C.

362 :
363 ParallelObject(parent),
364 ex_id(0),
365 ex_err(0),
366 header_info(), // zero-initialize
385 num_attr(0),
391 num_elem_vars(0),
392 verbose(v),
394 opened_for_writing(false),
395 opened_for_reading(false),
396 _run_only_on_proc0(run_only_on_proc0),
397 _opened_by_create(false),
402 _write_hdf5(true),
404 _end_elem_id(0),
406 _single_precision(single_precision)
407{
408 title.resize(MAX_LINE_LENGTH+1);
409 elem_type.resize(libmesh_max_str_length);
412}
An object whose state is distributed along a set of processors.

References elem_type, init_conversion_map(), init_element_equivalence_map(), and title.

◆ ExodusII_IO_Helper() [2/3]

libMesh::ExodusII_IO_Helper::ExodusII_IO_Helper ( const ExodusII_IO_Helper &  )
default

Special functions.

This class does not manage any dynamically allocated resources (file pointers, etc.) so it should be default copy/move constructable, but I don't know if any existing code actually uses these operations.

◆ ExodusII_IO_Helper() [3/3]

libMesh::ExodusII_IO_Helper::ExodusII_IO_Helper ( ExodusII_IO_Helper &&  )
default

◆ ~ExodusII_IO_Helper()

libMesh::ExodusII_IO_Helper::~ExodusII_IO_Helper ( )
virtualdefault

Member Function Documentation

◆ added_node_offset_on()

dof_id_type libMesh::ExodusII_IO_Helper::added_node_offset_on ( processor_id_type  p) const
inline

Definition at line 985 of file exodusII_io_helper.h.

986 {
988 const dof_id_type added_node_offsets =
989 (_added_side_node_offsets.empty() || !p) ? 0 :
991 return _true_node_offsets[p] + added_node_offsets;
992 }
std::vector< dof_id_type > _true_node_offsets
If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS variables, we also need to know how many...
std::vector< dof_id_type > _added_side_node_offsets
If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS variables, _added_side_node_offsets[p] g...
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67

References _added_side_node_offsets, _true_node_offsets, and libMesh::libmesh_assert().

◆ check_existing_vars()

void libMesh::ExodusII_IO_Helper::check_existing_vars ( ExodusVarType  type,
std::vector< std::string > &  names,
std::vector< std::string > &  names_from_file 
)
protected

When appending: during initialization, check that variable names in the file match those you attempt to initialize with.

Definition at line 4149 of file exodusII_io_helper.C.

4152{
4153 // There may already be global variables in the file (for example,
4154 // if we're appending) and in that case, we
4155 // 1.) Cannot initialize them again.
4156 // 2.) Should check to be sure that the global variable names are the same.
4157
4158 // Fills up names_from_file for us
4159 this->read_var_names(type);
4160
4161 // Both the number of variables and their names (up to the first
4162 // MAX_STR_LENGTH characters) must match for the names we are
4163 // planning to write and the names already in the file.
4164 bool match =
4165 std::equal(names.begin(), names.end(),
4166 names_from_file.begin(),
4167 [this](const std::string & a,
4168 const std::string & b) -> bool
4169 {
4170 return a.compare(/*pos=*/0, /*len=*/_max_name_length, b) == 0;
4171 });
4172
4173 if (!match)
4174 {
4175 libMesh::err << "Error! The Exodus file already contains the variables:" << std::endl;
4176 for (const auto & name : names_from_file)
4177 libMesh::err << name << std::endl;
4178
4179 libMesh::err << "And you asked to write:" << std::endl;
4180 for (const auto & name : names)
4181 libMesh::err << name << std::endl;
4182
4183 libmesh_error_msg("Cannot overwrite existing variables in Exodus II file.");
4184 }
4185}
void read_var_names(ExodusVarType type)
static const Real b
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
The libMesh namespace provides an interface to certain functionality in the library.
OStreamProxy err

References b, libMesh::err, and read_var_names().

Referenced by initialize_element_variables(), libMesh::Nemesis_IO_Helper::initialize_element_variables(), initialize_global_variables(), and initialize_nodal_variables().

◆ close()

void libMesh::ExodusII_IO_Helper::close ( )
noexcept

Closes the ExodusII mesh file.

This function is called from the ExodusII_IO destructor, so it should not throw an exception.

Definition at line 2128 of file exodusII_io_helper.C.

2129{
2130 // Call ex_close on every processor that did ex_open or ex_create;
2131 // newer Exodus versions error if we try to reopen a file that
2132 // hasn't been officially closed. Don't close the file if we didn't
2133 // open it; this also raises an Exodus error.
2134
2135 // We currently do read-only ex_open on every proc (to do read
2136 // operations on every proc), but we do ex_open and ex_create for
2137 // writes on every proc only with Nemesis files.
2139 (this->processor_id() == 0) ||
2141 {
2143 {
2144 ex_err = exII::ex_close(ex_id);
2145 // close() is called from the destructor, so it may be called e.g.
2146 // during stack unwinding while processing an exception. In that case
2147 // we don't want to throw another exception or immediately terminate
2148 // the code, since that would prevent any possible recovery from the
2149 // exception in question. So we just log the error closing the file
2150 // and continue.
2151 if (ex_err < 0)
2152 message("Error closing Exodus file.");
2153 else
2154 message("Exodus file closed successfully.");
2155 }
2156 }
2157
2158 // Now that the file is closed, it's no longer opened for
2159 // reading or writing.
2160 opened_for_writing = false;
2161 opened_for_reading = false;
2162 _opened_by_create = false;
2163}
void message(std::string_view msg)
Prints the message defined in msg.
processor_id_type processor_id() const

References _opened_by_create, _run_only_on_proc0, ex_err, ex_id, message(), opened_for_reading, opened_for_writing, and libMesh::ParallelObject::processor_id().

Referenced by ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl(), and libMesh::Nemesis_IO_Helper::~Nemesis_IO_Helper().

◆ comm()

const Parallel::Communicator & libMesh::ParallelObject::comm ( ) const
inlineinherited
Returns
A reference to the Parallel::Communicator object used by this mesh.

Definition at line 97 of file parallel_object.h.

98 { return _communicator; }
const Parallel::Communicator & _communicator

References libMesh::ParallelObject::_communicator.

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::Partitioner::_find_global_index_by_pid_map(), libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult_add(), libMesh::DofMap::add_constraints_to_send_list(), add_cube_convex_hull_to_mesh(), libMesh::PetscDMWrapper::add_dofs_helper(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::TransientRBConstruction::add_IC_to_RB_space(), libMesh::RBEIMEvaluation::add_interpolation_data(), libMesh::CondensedEigenSystem::add_matrices(), libMesh::EigenSystem::add_matrices(), libMesh::System::add_matrix(), libMesh::System::add_matrix(), libMesh::System::add_matrix(), libMesh::RBConstruction::add_scaled_matrix_and_vector(), libMesh::System::add_vector(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::RBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::assemble_affine_expansion(), libMesh::AdvectionSystem::assemble_claw_rhs(), libMesh::FEMSystem::assemble_qoi(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::MeshCommunication::assign_global_indices(), libMesh::Partitioner::assign_partitioning(), libMesh::MeshTools::Generation::build_extrusion(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::PetscDMWrapper::build_section(), libMesh::PetscDMWrapper::build_sf(), libMesh::BoundaryInfo::build_side_list_from_node_list(), libMesh::MeshBase::cache_elem_data(), centroid_l2_error(), libMesh::DofMap::check_dirichlet_bcid_consistency(), libMesh::MeshTetInterface::check_hull_integrity(), MeshInputTest::checkHexPrismPolyhedron(), libMesh::MeshBase::complete_preparation(), libMesh::RBConstruction::compute_Fq_representor_innerprods(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::RBConstruction::compute_output_dual_innerprods(), libMesh::RBConstruction::compute_residual_dual_norm_slow(), libMesh::RBSCMConstruction::compute_SCM_bounds_on_training_set(), libMesh::DofMap::computed_sparsity_already(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), PetscSolverConfiguration::configure_solver(), libMesh::ContinuationSystem::ContinuationSystem(), libMesh::MeshBase::copy_constraint_rows(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::CondensedEigenSystem::copy_super_to_sub(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshBase::count_constraint_rows(), libMesh::MeshTools::create_bounding_box(), libMesh::DofMap::create_dof_constraints(), libMesh::MeshTools::create_nodal_bounding_box(), libMesh::MeshRefinement::create_parent_error_vector(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::MeshTools::create_subdomain_bounding_box(), libMesh::PetscMatrix< T >::create_submatrix_nosort(), create_wrapped_function(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::MeshBase::detect_interior_parents(), libMesh::RBEIMEvaluation::distribute_bfs(), DMlibMeshFunction(), DMlibMeshJacobian(), DMlibMeshSetSystem_libMesh(), DMVariableBounds_libMesh(), libMesh::DTKSolutionTransfer::DTKSolutionTransfer(), libMesh::MeshRefinement::eliminate_unrefined_patches(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_interiors(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_nodes(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_sides(), libMesh::TransientRBConstruction::enrich_RB_space(), libMesh::EpetraVector< T >::EpetraVector(), AssembleOptimization::equality_constraints(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::SmoothnessEstimator::estimate_smoothness(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::MeshRefinement::flag_elements_by_error_tolerance(), libMesh::MeshRefinement::flag_elements_by_mean_stddev(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::DofMap::gather_constraints(), libMesh::MeshfreeInterpolation::gather_remote_data(), libMesh::CondensedEigenSystem::get_eigenpair(), libMesh::RBEIMEvaluation::get_eim_basis_function_node_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_side_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_value(), libMesh::MeshBase::get_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::RBEIMConstruction::get_max_abs_value(), libMesh::RBEIMConstruction::get_node_max_abs_value(), libMesh::RBEIMEvaluation::get_parametrized_function_node_value(), libMesh::RBEIMEvaluation::get_parametrized_function_side_value(), libMesh::RBEIMEvaluation::get_parametrized_function_value(), libMesh::RBEIMConstruction::get_random_point(), libMesh::RBEIMConstruction::get_random_point(), libMesh::RBEIMConstruction::get_random_point(), libMesh::MeshTetInterface::improve_hull_integrity(), AssembleOptimization::inequality_constraints(), AssembleOptimization::inequality_constraints_jacobian(), libMesh::StaticCondensation::init(), libMesh::TimeSolver::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::LocationMap< T >::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), ElasticitySystem::init_data(), libMesh::AdvectionSystem::init_data(), libMesh::ClawSystem::init_data(), libMesh::PetscDMWrapper::init_petscdm(), initialize(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), libMesh::RBEIMConstruction::initialize_parametrized_functions_in_training_set(), libMesh::RBEIMConstruction::inner_product(), integrate_function(), libMesh::MeshTools::Modification::interpolate_surface(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_equal_connectivity(), libMesh::MeshTools::libmesh_assert_equal_points(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_constraint_rows(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_flags(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_p_levels(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshTools::libmesh_assert_valid_unique_ids(), libMesh::libmesh_petsc_linesearch_shellfunc(), libMesh::libmesh_petsc_preconditioner_apply(), libMesh::libmesh_petsc_snes_postcheck(), libMesh::MeshRefinement::limit_level_mismatch_at_edge(), libMesh::MeshRefinement::limit_level_mismatch_at_node(), libMesh::MeshRefinement::limit_overrefined_boundary(), libMesh::MeshRefinement::limit_underrefined_boundary(), libMesh::LinearImplicitSystem::LinearImplicitSystem(), main(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), libMesh::MeshCommunication::make_node_bcids_parallel_consistent(), libMesh::MeshCommunication::make_node_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), libMesh::TransientRBConstruction::mass_matrix_scaled_matvec(), libMesh::FEMSystem::mesh_position_set(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), LinearElasticityWithContact::move_mesh(), libMesh::DistributedMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::DofMap::n_constrained_dofs(), libMesh::DofMap::n_dofs(), libMesh::DofMap::n_dofs_per_processor(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), MixedOrderTest::n_neighbor_links(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::SparsityPattern::Build::n_nonzeros(), libMesh::MeshTools::n_p_levels(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::RBEIMEvaluation::node_distribute_bfs(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::RBEIMConstruction::node_inner_product(), libMesh::PetscVector< T >::operator=(), libMesh::MeshBase::operator==(), libMesh::DistributedMesh::parallel_max_elem_id(), libMesh::DistributedMesh::parallel_max_node_id(), libMesh::DistributedMesh::parallel_max_unique_id(), libMesh::ReplicatedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_n_elem(), libMesh::DistributedMesh::parallel_n_nodes(), libMesh::SparsityPattern::Build::parallel_sync(), libMesh::BoundaryInfo::parallel_sync_node_ids(), libMesh::BoundaryInfo::parallel_sync_side_ids(), libMesh::MeshTools::paranoid_n_levels(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::petsc_auto_fieldsplit(), MeshGenerationTest::polyhedronTetNeighbor(), LaplaceSystem::postprocess(), PoissonSystem::postprocess(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::DofMap::process_mesh_constraint_rows(), libMesh::Partitioner::processor_pairs_to_interface_nodes(), libMesh::InterMeshProjection::project_system_vectors(), libMesh::XdrIO::read(), libMesh::Nemesis_IO::read(), FEMParameters::read(), libMesh::EquationSystems::read(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::RBEIMEvaluation::read_in_interior_basis_functions(), libMesh::RBEIMEvaluation::read_in_node_basis_functions(), libMesh::RBEIMEvaluation::read_in_side_basis_functions(), libMesh::RBEvaluation::read_in_vectors_from_multiple_files(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), MeshFunctionTest::read_variable_info_from_output_data(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::BoundaryInfo::remove_edge_id(), libMesh::BoundaryInfo::remove_node_id(), libMesh::BoundaryInfo::remove_shellface_id(), libMesh::BoundaryInfo::remove_side_id(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), LinearElasticityWithContact::residual_and_jacobian(), OverlappingAlgebraicGhostingTest::run_ghosting_test(), OverlappingCouplingGhostingTest::run_sparsity_pattern_test(), scale_mesh_and_plot(), libMesh::DofMap::scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::send_and_insert_dof_values(), libMesh::TransientRBConstruction::set_error_temporal_data(), libMesh::Partitioner::set_interface_node_processor_ids_BFS(), libMesh::Partitioner::set_interface_node_processor_ids_linear(), libMesh::Partitioner::set_interface_node_processor_ids_petscpartitioner(), libMesh::Partitioner::set_node_processor_ids(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::RBEIMEvaluation::side_distribute_bfs(), libMesh::RBEIMEvaluation::side_gather_bfs(), libMesh::RBEIMConstruction::side_inner_product(), libMesh::Partitioner::single_partition(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::VariationalMeshSmoother::smooth(), libMesh::NoxNonlinearSolver< Number >::solve(), libMesh::ClawSystem::solve_conservation_law(), libMesh::split_mesh(), libMesh::RBEIMConstruction::store_eim_solutions_for_training_set(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), libMesh::MeshBase::sync_subdomain_name_map(), ConstraintOperatorTest::test1DCoarseningNewNodes(), ConstraintOperatorTest::test1DCoarseningOperator(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), MeshfunctionDFEM::test_mesh_function_dfem(), MeshfunctionDFEM::test_mesh_function_dfem_grad(), MeshFunctionTest::test_p_level(), ExodusC0PolyhedronTest::test_write_and_read_hexagonal_prism(), ExodusC0PolygonTest::test_write_and_read_pentagon(), DofMapTest::testBadElemFECombo(), SystemsTest::testBlockRestrictedVarNDofs(), BoundaryInfoTest::testBoundaryOnChildrenErrors(), MeshGenerationTest::testBuildCube(), BoundaryInfoTest::testBuildSideListFromNodeListThinMesh(), CheckpointIOTest::testC0PolygonCheckpoint(), VolumeTest::testC0PolygonMethods(), CheckpointIOTest::testC0PolyhedronCheckpoint(), VolumeTest::testC0PolyhedronMethods(), ConstraintOperatorTest::testCoreform(), ConnectedComponentsTest::testEdge(), MeshInputTest::testExodusIGASidesets(), MeshTriangulationTest::testFoundCenters(), PointLocatorTest::testLocator(), BoundaryInfoTest::testMesh(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), PointLocatorTest::testPlanar(), MeshTriangulationTest::testPoly2TriEdge3ToTri7CenterFixup(), MeshTriangulationTest::testPoly2TriRefinementBase(), SystemsTest::testProjectCubeWithMeshFunction(), SystemsTest::testProjectScalarCoarsening(), BoundaryInfoTest::testRenumber(), BoundaryInfoTest::testSelectiveRenumber(), BoundaryMeshSubdomainTest::testSingleSubdomain(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshTriangulationTest::testTriangulatorInterp(), MeshTriangulationTest::testTriangulatorMeshedHoles(), MeshTriangulationTest::testTriangulatorRoundHole(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::RBConstruction::train_reduced_basis_with_POD(), libMesh::MeshfreeSolutionTransfer::transfer(), libMesh::MeshFunctionSolutionTransfer::transfer(), libMesh::Poly2TriTriangulator::triangulate(), libMesh::RBConstruction::truth_assembly(), libMesh::TransientRBConstruction::truth_assembly(), update_current_local_solution(), libMesh::TransientRBConstruction::update_RB_initial_condition_all_N(), libMesh::RBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_residual_terms(), libMesh::RBConstruction::update_residual_terms(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::XdrIO::write(), libMesh::NameBasedIO::write(), libMesh::VTKIO::write_nodal_data(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), libMesh::RBEvaluation::write_out_vectors(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::TransientRBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::RBDataSerialization::RBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::TransientRBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::RBEIMEvaluationSerialization::write_to_file(), and libMesh::RBDataSerialization::RBSCMEvaluationSerialization::write_to_file().

◆ conditionally_set_elem_unique_id()

void libMesh::ExodusII_IO_Helper::conditionally_set_elem_unique_id ( MeshBase &  mesh,
Elem *  elem,
int  zero_based_elem_num_map_index 
)

Definition at line 2557 of file exodusII_io_helper.C.

2559{
2560 this->set_dof_object_unique_id(mesh, elem, libmesh_vector_at(this->elem_num_map, zero_based_elem_num_map_index));
2561}
void set_dof_object_unique_id(MeshBase &mesh, DofObject *dof_object, int exodus_mapped_id)

References elem_num_map, and set_dof_object_unique_id().

◆ conditionally_set_node_unique_id()

void libMesh::ExodusII_IO_Helper::conditionally_set_node_unique_id ( MeshBase &  mesh,
Node *  node,
int  zero_based_node_num_map_index 
)

Helper function that conditionally sets the unique_id of the passed-in Node/Elem.

Calling this function does nothing if _set_unique_ids_from_maps == false, otherwise it sets the unique_id based on the entries of the {node,elem_num_map}. The input index is assumed to be a zero-based index into the {node,elem}_num_map array.

Definition at line 2550 of file exodusII_io_helper.C.

2552{
2553 this->set_dof_object_unique_id(mesh, node, libmesh_vector_at(this->node_num_map, zero_based_node_num_map_index));
2554}

References node_num_map, and set_dof_object_unique_id().

◆ create()

void libMesh::ExodusII_IO_Helper::create ( std::string  filename)
virtual

Opens an ExodusII mesh file named filename for writing.

Definition at line 2601 of file exodusII_io_helper.C.

2602{
2603 // If we're processor 0, always create the file.
2604 // If we running on all procs, e.g. as one of several Nemesis files, also
2605 // call create there.
2606 if ((this->processor_id() == 0) || (!_run_only_on_proc0))
2607 {
2608 int
2609 comp_ws = 0,
2610 io_ws = 0;
2611
2613 {
2614 comp_ws = cast_int<int>(sizeof(float));
2615 io_ws = cast_int<int>(sizeof(float));
2616 }
2617 // Fall back on double precision when necessary since ExodusII
2618 // doesn't seem to support long double
2619 else
2620 {
2621 comp_ws = cast_int<int>
2622 (std::min(sizeof(Real), sizeof(double)));
2623 io_ws = cast_int<int>
2624 (std::min(sizeof(Real), sizeof(double)));
2625 }
2626
2627 // By default we just open the Exodus file in "EX_CLOBBER" mode,
2628 // which, according to "ncdump -k", writes the file in "64-bit
2629 // offset" mode, which is a NETCDF3 file format.
2630 int mode = EX_CLOBBER;
2631
2632 // If HDF5 is available, by default we will write Exodus files
2633 // in a more modern NETCDF4-compatible format. For this file
2634 // type, "ncdump -k" will report "netCDF-4".
2635#ifdef LIBMESH_HAVE_HDF5
2636 if (this->_write_hdf5)
2637 {
2638 mode |= EX_NETCDF4;
2639 mode |= EX_NOCLASSIC;
2640 }
2641#endif
2642
2643 {
2644 FPEDisabler disable_fpes;
2645 ex_id = exII::ex_create(filename.c_str(), mode, &comp_ws, &io_ws);
2646 }
2647
2648 EX_CHECK_ERR(ex_id, "Error creating ExodusII/Nemesis mesh file.");
2649
2650 // We don't have access to the names we might be writing until we
2651 // write them, so we can't set a guaranteed max name length here.
2652 // But it looks like the most ExodusII can support is 80, so we'll
2653 // just waste 48 bytes here and there.
2654 ex_err = exII::ex_set_max_name_length(ex_id, _max_name_length);
2655 EX_CHECK_ERR(ex_err, "Error setting max ExodusII name length.");
2656
2657 if (verbose)
2658 libMesh::out << "File created successfully." << std::endl;
2659 }
2660
2661 opened_for_writing = true;
2662 _opened_by_create = true;
2663 current_filename = filename;
2664}
OStreamProxy out
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
The FPEDisabler class puts Floating-Point Exception (FPE) trapping on hold during its lifetime,...

References _max_name_length, _opened_by_create, _run_only_on_proc0, _single_precision, _write_hdf5, current_filename, ex_err, ex_id, opened_for_writing, libMesh::out, libMesh::ParallelObject::processor_id(), libMesh::Real, and verbose.

Referenced by ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl().

◆ end_elem_id()

int libMesh::ExodusII_IO_Helper::end_elem_id ( ) const
inline

Definition at line 1374 of file exodusII_io_helper.h.

1375{
1376 libmesh_assert_equal_to(std::size_t(num_elem), elem_num_map.size());
1377 return _end_elem_id;
1378}

References _end_elem_id, elem_num_map, and num_elem.

◆ get_add_sides()

bool libMesh::ExodusII_IO_Helper::get_add_sides ( )
inline

Definition at line 1368 of file exodusII_io_helper.h.

1369{
1370 return _add_sides;
1371}
bool _add_sides
Set to true iff we want to write separate "side" elements too.

References _add_sides.

◆ get_block_id()

int libMesh::ExodusII_IO_Helper::get_block_id ( int  index)

Get the block number for the given block index.

Definition at line 1237 of file exodusII_io_helper.C.

1238{
1239 libmesh_assert_less (index, block_ids.size());
1240
1241 return block_ids[index];
1242}

References block_ids.

Referenced by write_element_values(), and write_element_values_element_major().

◆ get_block_name()

std::string libMesh::ExodusII_IO_Helper::get_block_name ( int  index)

Get the block name for the given block index if supplied in the mesh file.

Otherwise an empty string is returned.

Definition at line 1246 of file exodusII_io_helper.C.

1247{
1248 libmesh_assert_less (index, block_ids.size());
1249
1250 return id_to_block_names[block_ids[index]];
1251}
std::map< int, std::string > id_to_block_names

References block_ids, and id_to_block_names.

◆ get_complex_names()

std::vector< std::string > libMesh::ExodusII_IO_Helper::get_complex_names ( const std::vector< std::string > &  names,
bool  write_complex_abs 
) const
Returns
A vector with three copies of each element in the provided name vector, starting with r_, i_ and a_ respectively. If the "write_complex_abs" parameter is true (default), the complex modulus is written, otherwise only the real and imaginary parts are written.

Definition at line 5506 of file exodusII_io_helper.C.

5508{
5509 std::vector<std::string> complex_names;
5510
5511 // This will loop over all names and create new "complex" names
5512 // (i.e. names that start with r_, i_ or a_)
5513 for (const auto & name : names)
5514 {
5515 complex_names.push_back("r_" + name);
5516 complex_names.push_back("i_" + name);
5517 if (write_complex_abs)
5518 complex_names.push_back("a_" + name);
5519 }
5520
5521 return complex_names;
5522}

◆ get_complex_subdomain_to_var_names()

std::map< subdomain_id_type, std::vector< std::string > > libMesh::ExodusII_IO_Helper::get_complex_subdomain_to_var_names ( const std::map< subdomain_id_type, std::vector< std::string > > &  subdomain_to_var_names,
bool  write_complex_abs 
) const

Takes a map from subdomain id -> vector of active variable names as input and returns a corresponding map where the original variable names have been replaced by their complex counterparts.

Used by the ExodusII_IO::write_element_data_from_discontinuous_nodal_data() function.

Definition at line 5550 of file exodusII_io_helper.C.

5554{
5555 // Eventual return value
5556 std::map<subdomain_id_type, std::vector<std::string>> ret;
5557
5558 unsigned int num_complex_outputs = write_complex_abs ? 3 : 2;
5559
5560 for (const auto & pr : subdomain_to_var_names)
5561 {
5562 // Initialize entry for current subdomain
5563 auto & vec = ret[pr.first];
5564
5565 // Get list of non-complex variable names active on this subdomain.
5566 const auto & varnames = pr.second;
5567
5568 // Allocate space for the complex-valued entries
5569 vec.reserve(num_complex_outputs * varnames.size());
5570
5571 // For each varname in the input map, write three variable names
5572 // to the output formed by prepending "r_", "i_", and "a_",
5573 // respectively.
5574 for (const auto & varname : varnames)
5575 {
5576 vec.push_back("r_" + varname);
5577 vec.push_back("i_" + varname);
5578 if (write_complex_abs)
5579 vec.push_back("a_" + varname);
5580 }
5581 }
5582 return ret;
5583}

◆ get_complex_vars_active_subdomains()

std::vector< std::set< subdomain_id_type > > libMesh::ExodusII_IO_Helper::get_complex_vars_active_subdomains ( const std::vector< std::set< subdomain_id_type > > &  vars_active_subdomains,
bool  write_complex_abs 
) const

returns a "tripled" copy of vars_active_subdomains, which is necessary in the complex-valued case.

Definition at line 5527 of file exodusII_io_helper.C.

5531{
5532 std::vector<std::set<subdomain_id_type>> complex_vars_active_subdomains;
5533
5534 for (auto & s : vars_active_subdomains)
5535 {
5536 // Push back the same data enough times for the real, imag, (and
5537 // possibly modulus) for the complex-valued solution.
5538 complex_vars_active_subdomains.push_back(s);
5539 complex_vars_active_subdomains.push_back(s);
5540 if (write_complex_abs)
5541 complex_vars_active_subdomains.push_back(s);
5542 }
5543
5544 return complex_vars_active_subdomains;
5545}

◆ get_conversion() [1/2]

const ExodusII_IO_Helper::Conversion & libMesh::ExodusII_IO_Helper::get_conversion ( const ElemType  type) const

Definition at line 660 of file exodusII_io_helper.C.

661{
662 auto & maps_for_dim = libmesh_map_find(conversion_map, this->num_dim);
663 return libmesh_map_find(maps_for_dim, type);
664}
std::map< int, std::map< ElemType, ExodusII_IO_Helper::Conversion > > conversion_map
Associates libMesh ElemTypes with node/face/edge/etc.

References conversion_map, and num_dim.

Referenced by libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), get_conversion(), get_sideset_data_indices(), read_edge_blocks(), read_elem_in_block(), read_face_blocks(), read_sideset_data(), write_elements(), libMesh::Nemesis_IO_Helper::write_elements(), write_sideset_data(), write_sidesets(), and libMesh::Nemesis_IO_Helper::write_sidesets().

◆ get_conversion() [2/2]

const ExodusII_IO_Helper::Conversion & libMesh::ExodusII_IO_Helper::get_conversion ( std::string  type_str) const

Definition at line 667 of file exodusII_io_helper.C.

668{
669 // Do only upper-case comparisons
670 std::transform(type_str.begin(), type_str.end(), type_str.begin(), ::toupper);
671 return get_conversion (libmesh_map_find(element_equivalence_map, type_str));
672}
std::map< std::string, ElemType > element_equivalence_map
Defines equivalence classes of Exodus element types that map to libmesh ElemTypes.
const ExodusII_IO_Helper::Conversion & get_conversion(const ElemType type) const

References element_equivalence_map, and get_conversion().

◆ get_elem_type()

const char * libMesh::ExodusII_IO_Helper::get_elem_type ( ) const
Returns
The current element type.
Note
The default behavior is for this value to be in all capital letters, e.g. HEX27.

Definition at line 674 of file exodusII_io_helper.C.

675{
676 return elem_type.data();
677}

References elem_type.

◆ get_elemset_data_indices()

void libMesh::ExodusII_IO_Helper::get_elemset_data_indices ( std::map< std::pair< dof_id_type, elemset_id_type >, unsigned int > &  elemset_array_indices)

Similar to read_elemset_data(), but instead of creating one std::map per elemset per variable, creates a single map of (elem_id, elemset_id) tuples, and stores the exo file array indexing for any/all elemset variables on that elemset (they are all the same).

Definition at line 4937 of file exodusII_io_helper.C.

4939{
4940 // Clear existing data, we are going to build these data structures from scratch
4941 elemset_array_indices.clear();
4942
4943 // Read the elemset data.
4944 //
4945 // Note: we assume that the functions
4946 // 1.) this->read_elemset_info() and
4947 // 2.) this->read_elemset()
4948 // have already been called, so that we already know e.g. how
4949 // many elems are in each set, their ids, etc.
4950 int offset=0;
4951 for (int es=0; es<num_elem_sets; ++es)
4952 {
4953 offset += (es > 0 ? num_elems_per_set[es-1] : 0);
4954
4955 // Note: we don't actually call exII::ex_get_var() here because
4956 // we don't need the values. We only need the indices into that vector
4957 // for each (elem_id, elemset_id) tuple.
4958 for (int i=0; i<num_elems_per_set[es]; ++i)
4959 {
4960 dof_id_type exodus_elem_id = elemset_list[i + offset];
4961
4962 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4963 // but it apparently is never set up, so just
4964 // subtract 1 from the Exodus elem id.
4965 dof_id_type converted_elem_id = exodus_elem_id - 1;
4966
4967 // Make key based on the elem and set ids
4968 // Make a NodeBCTuple key from the converted information.
4969 auto key = std::make_pair(converted_elem_id,
4970 static_cast<elemset_id_type>(elemset_ids[es]));
4971
4972 // Store the array index of this (node, b_id) tuple
4973 elemset_array_indices.emplace(key, cast_int<unsigned int>(i));
4974 } // end for (i)
4975 } // end for (es)
4976}
std::vector< int > num_elems_per_set

References elemset_ids, elemset_list, num_elem_sets, and num_elems_per_set.

◆ get_exodus_version()

int libMesh::ExodusII_IO_Helper::get_exodus_version ( )
static
Returns
The ExodusII API version, in "nodot" format; e.g. 822 for 8.22

Definition at line 420 of file exodusII_io_helper.C.

421{
422 return EX_API_VERS_NODOT;
423}

Referenced by libMesh::ExodusII_IO::get_exodus_version().

◆ get_libmesh_elem_id()

dof_id_type libMesh::ExodusII_IO_Helper::get_libmesh_elem_id ( int  exodus_elem_id)

Definition at line 2511 of file exodusII_io_helper.C.

2512{
2513 return this->get_libmesh_id(exodus_elem_id, this->elem_num_map);
2514}
dof_id_type get_libmesh_id(int exodus_id, const std::vector< int > &num_map)
Internal implementation for the two sets of functions above.

References elem_num_map, and get_libmesh_id().

Referenced by read_elemental_var_values().

◆ get_libmesh_id()

dof_id_type libMesh::ExodusII_IO_Helper::get_libmesh_id ( int  exodus_id,
const std::vector< int > &  num_map 
)
private

Internal implementation for the two sets of functions above.

Definition at line 2517 of file exodusII_io_helper.C.

2519{
2520 // The input exodus_id is assumed to be a (1-based) index into
2521 // the {node,elem}_num_map, so in order to use exodus_id as an index
2522 // in C++, we need to first make it zero-based.
2523 auto exodus_id_zero_based =
2524 cast_int<dof_id_type>(exodus_id - 1);
2525
2526 // Throw an informative error message rather than accessing past the
2527 // end of the provided num_map. If we are setting Elem unique_ids
2528 // based on the num_map, we don't need to do this check.
2529 if (!this->set_unique_ids_from_maps)
2530 libmesh_error_msg_if(exodus_id_zero_based >= num_map.size(),
2531 "Cannot get LibMesh id for Exodus id: " << exodus_id);
2532
2533 // If the user set the flag which stores Exodus node/elem ids as
2534 // unique_ids instead of regular ids, then the libmesh id we are
2535 // looking for is actually just "exodus_id_zero_based". Otherwise,
2536 // we need to look up the Node/Elem's id in the provided num_map,
2537 // *and* then subtract 1 from that because the entries in the
2538 // num_map are also 1-based.
2539 dof_id_type libmesh_id =
2541 cast_int<dof_id_type>(exodus_id_zero_based) :
2542 cast_int<dof_id_type>(num_map[exodus_id_zero_based] - 1);
2543
2544 return libmesh_id;
2545}
Tnew cast_int(Told oldvar)

References set_unique_ids_from_maps.

Referenced by get_libmesh_elem_id(), and get_libmesh_node_id().

◆ get_libmesh_node_id()

dof_id_type libMesh::ExodusII_IO_Helper::get_libmesh_node_id ( int  exodus_node_id)

Helper function that takes a (1-based) Exodus node/elem id and determines the corresponding libMesh Node/Elem id.

Takes into account whether the user has chosen to set the Node/Elem unique ids based on the {node,elem}_num_map or to let libMesh set them.

Definition at line 2506 of file exodusII_io_helper.C.

2507{
2508 return this->get_libmesh_id(exodus_node_id, this->node_num_map);
2509}

References get_libmesh_id(), and node_num_map.

Referenced by read_edge_blocks(), and read_nodal_var_values().

◆ get_node_set_id()

int libMesh::ExodusII_IO_Helper::get_node_set_id ( int  index)

Get the node set id for the given node set index.

Definition at line 1273 of file exodusII_io_helper.C.

1274{
1275 libmesh_assert_less (index, nodeset_ids.size());
1276
1277 return nodeset_ids[index];
1278}

References nodeset_ids.

◆ get_node_set_name()

std::string libMesh::ExodusII_IO_Helper::get_node_set_name ( int  index)

Get the node set name for the given node set index if supplied in the mesh file.

Otherwise an empty string is returned.

Definition at line 1282 of file exodusII_io_helper.C.

1283{
1284 libmesh_assert_less (index, nodeset_ids.size());
1285
1286 return id_to_ns_names[nodeset_ids[index]];
1287}
std::map< int, std::string > id_to_ns_names

References id_to_ns_names, and nodeset_ids.

◆ get_nodeset_data_indices()

void libMesh::ExodusII_IO_Helper::get_nodeset_data_indices ( std::map< BoundaryInfo::NodeBCTuple, unsigned int > &  bc_array_indices)

Similar to read_nodeset_data(), but instead of creating one std::map per nodeset per variable, creates a single map of (node_id, boundary_id) tuples, and stores the exo file array indexing for any/all nodeset variables on that nodeset (they are all the same).

Definition at line 5079 of file exodusII_io_helper.C.

5081{
5082 // Clear existing data, we are going to build these data structures from scratch
5083 bc_array_indices.clear();
5084
5085 // Read the nodeset data.
5086 //
5087 // Note: we assume that the functions
5088 // 1.) this->read_nodeset_info() and
5089 // 2.) this->read_all_nodesets()
5090 // have already been called, so that we already know e.g. how
5091 // many nodes are in each set, their ids, etc.
5092 int offset=0;
5093 for (int ns=0; ns<num_node_sets; ++ns)
5094 {
5095 offset += (ns > 0 ? num_nodes_per_set[ns-1] : 0);
5096 // Note: we don't actually call exII::ex_get_var() here because
5097 // we don't need the values. We only need the indices into that vector
5098 // for each (node_id, boundary_id) tuple.
5099 for (int i=0; i<num_nodes_per_set[ns]; ++i)
5100 {
5101 // The read_all_nodesets() function now reads all the node ids into the
5102 // node_sets_node_list vector, which is of length "total_nodes_in_all_sets"
5103 // The old read_nodset() function is no longer called as far as I can tell,
5104 // and should probably be removed? The "offset" that we are using only
5105 // depends on the current nodeset index and the num_nodes_per_set vector,
5106 // which gets filled in by the call to read_all_nodesets().
5107 dof_id_type exodus_node_id = node_sets_node_list[i + offset];
5108
5109 // FIXME: We should use exodus_node_num_to_libmesh for this,
5110 // but it apparently is never set up, so just
5111 // subtract 1 from the Exodus node id.
5112 dof_id_type converted_node_id = exodus_node_id - 1;
5113
5114 // Make a NodeBCTuple key from the converted information.
5115 BoundaryInfo::NodeBCTuple key = std::make_tuple
5116 (converted_node_id, nodeset_ids[ns]);
5117
5118 // Store the array index of this (node, b_id) tuple
5119 bc_array_indices.emplace(key, cast_int<unsigned int>(i));
5120 } // end for (i)
5121 } // end for (ns)
5122}
std::tuple< dof_id_type, boundary_id_type > NodeBCTuple
Create a list of (node_id, boundary_id) tuples for all relevant nodes.
std::vector< int > num_nodes_per_set
std::vector< int > node_sets_node_list

References node_sets_node_list, nodeset_ids, num_node_sets, and num_nodes_per_set.

◆ get_side_set_id()

int libMesh::ExodusII_IO_Helper::get_side_set_id ( int  index)

Get the side set id for the given side set index.

Definition at line 1255 of file exodusII_io_helper.C.

1256{
1257 libmesh_assert_less (index, ss_ids.size());
1258
1259 return ss_ids[index];
1260}

References ss_ids.

◆ get_side_set_name()

std::string libMesh::ExodusII_IO_Helper::get_side_set_name ( int  index)

Get the side set name for the given side set index if supplied in the mesh file.

Otherwise an empty string is returned.

Definition at line 1264 of file exodusII_io_helper.C.

1265{
1266 libmesh_assert_less (index, ss_ids.size());
1267
1268 return id_to_ss_names[ss_ids[index]];
1269}
std::map< int, std::string > id_to_ss_names

References id_to_ss_names, and ss_ids.

◆ get_sideset_data_indices()

void libMesh::ExodusII_IO_Helper::get_sideset_data_indices ( const MeshBase &  mesh,
std::map< BoundaryInfo::BCTuple, unsigned int > &  bc_array_indices 
)

Similar to read_sideset_data(), but instead of creating one std::map per sideset per variable, creates a single map of (elem, side, boundary_id) tuples, and stores the exo file array indexing for any/all sideset variables on that sideset (they are all the same).

This function does not actually call exII::ex_get_sset_var() to get values, and can be useful if only the original ordering of (elem, side) pairs in the exo file is required in cases where a separate approach is used to read the sideset data arrays.

Definition at line 4552 of file exodusII_io_helper.C.

4555{
4556 // Clear any existing data, we are going to build this data structure from scratch
4557 bc_array_indices.clear();
4558
4559 // Store the sideset data array indices.
4560 //
4561 // Note: we assume that read_sideset() has already been called
4562 // for each sideset, so the required values in elem_list and
4563 // side_list are already present.
4564 int offset=0;
4565 for (int ss=0; ss<num_side_sets; ++ss)
4566 {
4567 offset += (ss > 0 ? num_sides_per_set[ss-1] : 0);
4568 for (int i=0; i<num_sides_per_set[ss]; ++i)
4569 {
4570 dof_id_type exodus_elem_id = elem_list[i + offset];
4571 unsigned int exodus_side_id = side_list[i + offset];
4572
4573 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4574 // but it apparently is never set up, so just
4575 // subtract 1 from the Exodus elem id.
4576 dof_id_type converted_elem_id = exodus_elem_id - 1;
4577
4578 // Conversion operator for this Elem type
4579 const auto & conv = get_conversion(mesh.elem_ptr(converted_elem_id)->type());
4580
4581 // Map from Exodus side id to libmesh side id.
4582 // Note: the mapping is defined on 0-based indices, so subtract
4583 // 1 before doing the mapping.
4584 unsigned int converted_side_id = conv.get_side_map(exodus_side_id - 1);
4585
4586 // Make a BCTuple key from the converted information.
4587 BoundaryInfo::BCTuple key = std::make_tuple
4588 (converted_elem_id,
4589 converted_side_id,
4590 ss_ids[ss]);
4591
4592 // Store (elem, side, b_id) tuple with corresponding array index
4593 bc_array_indices.emplace(key, cast_int<unsigned int>(i));
4594 } // end for (i)
4595 } // end for (ss)
4596}
std::tuple< dof_id_type, unsigned short int, boundary_id_type > BCTuple
Create a list of (element_id, side_id, boundary_id) tuples for relevant sides.
virtual ElemType type() const =0
std::vector< int > num_sides_per_set
virtual const Elem * elem_ptr(const dof_id_type i) const =0
MeshBase & mesh

References elem_list, libMesh::MeshBase::elem_ptr(), get_conversion(), mesh, num_side_sets, num_sides_per_set, side_list, ss_ids, and libMesh::Elem::type().

◆ init_conversion_map()

void libMesh::ExodusII_IO_Helper::init_conversion_map ( )
private

Definition at line 428 of file exodusII_io_helper.C.

429{
430 auto convert_type = [this](ElemType type,
431 std::string_view exodus_type,
432 const std::vector<int> * node_map = nullptr,
433 const std::vector<int> * inverse_node_map = nullptr,
434 const std::vector<int> * side_map = nullptr,
435 const std::vector<int> * inverse_side_map = nullptr,
436 const std::vector<int> * shellface_map = nullptr,
437 const std::vector<int> * inverse_shellface_map = nullptr,
438 size_t shellface_index_offset = 0)
439 {
440 std::unique_ptr<Elem> elem = Elem::build(type);
441 auto & conv = conversion_map[elem->dim()][type];
442 conv.libmesh_type = type;
443 conv.exodus_type = exodus_type;
444 conv.node_map = node_map;
445 conv.inverse_node_map = inverse_node_map;
446 conv.side_map = side_map;
447 conv.inverse_side_map = inverse_side_map;
448 conv.shellface_map = shellface_map;
449 conv.inverse_shellface_map = inverse_shellface_map;
450 conv.shellface_index_offset = shellface_index_offset;
451 conv.n_nodes = elem->n_nodes();
452 for (int d = elem->dim()+1; d <= 3; ++d)
453 conversion_map[d][type] = conv;
454 };
455
456 convert_type(NODEELEM, "SPHERE");
457 convert_type(EDGE2, "EDGE2");
458 convert_type(EDGE3, "EDGE3");
459 convert_type(EDGE4, "EDGE4");
460 convert_type(QUAD4, "QUAD4");
461 convert_type(QUAD8, "QUAD8");
462 convert_type(QUAD9, "QUAD9");
463 convert_type(C0POLYGON, "NSIDED");
464 {
465 auto & conv = conversion_map[3][C0POLYHEDRON];
466 conv.libmesh_type = C0POLYHEDRON;
467 conv.exodus_type = "NFACED";
468 conv.dim = 3;
469 conv.n_nodes = 0;
470 }
471 convert_type(QUADSHELL4, "SHELL4", nullptr, nullptr, nullptr,
472 /* inverse_side_map = */ &quadshell4_inverse_edge_map,
473 nullptr, nullptr, /* shellface_index_offset = */ 2);
474 convert_type(QUADSHELL8, "SHELL8", nullptr, nullptr, nullptr,
475 /* inverse_side_map = */ &quadshell4_inverse_edge_map,
476 nullptr, nullptr, /* shellface_index_offset = */ 2);
477 convert_type(QUADSHELL9, "SHELL9", nullptr, nullptr, nullptr,
478 /* inverse_side_map = */ &quadshell4_inverse_edge_map,
479 nullptr, nullptr, /* shellface_index_offset = */ 2);
480
481 convert_type(TRI3, "TRI3");
482 convert_type(TRI6, "TRI6");
483 convert_type(TRI7, "TRI7");
484 // Exodus does weird things to triangle side mapping in 3D. See
485 // https://sandialabs.github.io/seacas-docs/html/element_types.html#tri
486 conversion_map[3][TRI3].inverse_side_map = &trishell3_inverse_edge_map;
487 conversion_map[3][TRI3].shellface_index_offset = 2;
488 conversion_map[3][TRI6].inverse_side_map = &trishell3_inverse_edge_map;
489 conversion_map[3][TRI6].shellface_index_offset = 2;
490 conversion_map[3][TRI7].inverse_side_map = &trishell3_inverse_edge_map;
491 conversion_map[3][TRI7].shellface_index_offset = 2;
492
493 convert_type(TRISHELL3, "TRISHELL3", nullptr, nullptr, nullptr,
494 /* inverse_side_map = */ &trishell3_inverse_edge_map,
495 nullptr, nullptr, /* shellface_index_offset = */ 2);
496 convert_type(TRI3SUBDIVISION, "TRI3");
497 convert_type(HEX8, "HEX8", nullptr, nullptr,
498 &hex_face_map, &hex_inverse_face_map);
499 convert_type(HEX20, "HEX20", nullptr, nullptr,
500 &hex_face_map, &hex_inverse_face_map);
501 convert_type(HEX27, "HEX27", &hex27_node_map,
502 &hex27_inverse_node_map,
503 &hex_face_map, &hex_inverse_face_map);
504 convert_type(TET4, "TETRA4", nullptr, nullptr,
505 &tet_face_map, &tet_inverse_face_map);
506 convert_type(TET10, "TETRA10", nullptr, nullptr,
507 &tet_face_map, &tet_inverse_face_map);
508 convert_type(TET14, "TETRA14", &tet14_node_map,
509 &tet14_inverse_node_map,
510 &tet_face_map, &tet_inverse_face_map);
511 convert_type(PRISM6, "WEDGE", nullptr, nullptr,
512 &prism_face_map, &prism_inverse_face_map);
513 convert_type(PRISM15, "WEDGE15", nullptr, nullptr,
514 &prism_face_map, &prism_inverse_face_map);
515 convert_type(PRISM18, "WEDGE18", nullptr, nullptr,
516 &prism_face_map, &prism_inverse_face_map);
517 convert_type(PRISM20, "WEDGE20", &prism20_node_map,
518 &prism20_inverse_node_map,
519 &prism_face_map, &prism_inverse_face_map);
520 convert_type(PRISM21, "WEDGE21", &prism21_node_map,
521 &prism21_inverse_node_map,
522 &prism_face_map, &prism_inverse_face_map);
523 convert_type(PYRAMID5, "PYRAMID5");
524 convert_type(PYRAMID13, "PYRAMID13");
525 convert_type(PYRAMID14, "PYRAMID14");
526 convert_type(PYRAMID18, "PYRAMID18");
527}
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:382
ElemType
Defines an enum for geometric element types.

References libMesh::Elem::build(), libMesh::C0POLYGON, libMesh::C0POLYHEDRON, conversion_map, libMesh::EDGE2, libMesh::EDGE3, libMesh::EDGE4, libMesh::HEX20, libMesh::HEX27, libMesh::HEX8, libMesh::NODEELEM, libMesh::PRISM15, libMesh::PRISM18, libMesh::PRISM20, libMesh::PRISM21, libMesh::PRISM6, libMesh::PYRAMID13, libMesh::PYRAMID14, libMesh::PYRAMID18, libMesh::PYRAMID5, libMesh::QUAD4, libMesh::QUAD8, libMesh::QUAD9, libMesh::QUADSHELL4, libMesh::QUADSHELL8, libMesh::QUADSHELL9, libMesh::TET10, libMesh::TET14, libMesh::TET4, libMesh::TRI3, libMesh::TRI3SUBDIVISION, libMesh::TRI6, libMesh::TRI7, and libMesh::TRISHELL3.

Referenced by ExodusII_IO_Helper().

◆ init_element_equivalence_map()

void libMesh::ExodusII_IO_Helper::init_element_equivalence_map ( )
private

Definition at line 533 of file exodusII_io_helper.C.

534{
535 // We use an ExodusII SPHERE element to represent a NodeElem
537
538 // EDGE2 equivalences
544 element_equivalence_map["TRUSS2"] = EDGE2;
547
548 // EDGE3 equivalences
550 element_equivalence_map["TRUSS3"] = EDGE3;
553
554 // EDGE4 equivalences
556 element_equivalence_map["TRUSS4"] = EDGE4;
559
560 // This whole design is going to need to be refactored whenever we
561 // support higher-order IGA, with one element type having variable
562 // polynomiaal degree...
563 element_equivalence_map["BEX_CURVE"] = EDGE3;
564
565 // QUAD4 equivalences
568
569 // QUADSHELL4 equivalences
572
573 // QUAD8 equivalences
575
576 // QUADSHELL8 equivalences
578
579 // QUAD9 equivalences
581 // This only supports p==2 IGA:
582 element_equivalence_map["BEX_QUAD"] = QUAD9;
583
584 // QUADSHELL9 equivalences
586
587 // Runtime-topology polytope equivalences
590
591 // TRI3 equivalences
594 element_equivalence_map["TRIANGLE"] = TRI3;
595
596 // TRISHELL3 equivalences
598 element_equivalence_map["TRISHELL3"] = TRISHELL3;
599
600 // TRI6 equivalences
602 // element_equivalence_map["TRISHELL6"] = TRI6;
603 // This only supports p==2 IGA:
604 element_equivalence_map["BEX_TRIANGLE"] = TRI6;
605
606 // TRI7 equivalences
608
609 // HEX8 equivalences
612
613 // HEX20 equivalences
615
616 // HEX27 equivalences
618 // This only supports p==2 IGA:
619 element_equivalence_map["BEX_HEX"] = HEX27;
620
621 // TET4 equivalences
622 element_equivalence_map["TETRA"] = TET4;
623 element_equivalence_map["TETRA4"] = TET4;
624
625 // TET10 equivalences
626 element_equivalence_map["TETRA10"] = TET10;
627 // This only supports p==2 IGA:
628 element_equivalence_map["BEX_TETRA"] = TET10;
629
630 // TET14 (in Exodus 8) equivalence
631 element_equivalence_map["TETRA14"] = TET14;
632
633 // PRISM6 equivalences
636
637 // PRISM15 equivalences
638 element_equivalence_map["WEDGE15"] = PRISM15;
639
640 // PRISM18 equivalences
641 element_equivalence_map["WEDGE18"] = PRISM18;
642 // This only supports p==2 IGA:
643 element_equivalence_map["BEX_WEDGE"] = PRISM18;
644
645 // PRISM20 equivalences
646 element_equivalence_map["WEDGE20"] = PRISM20;
647
648 // PRISM21 equivalences
649 element_equivalence_map["WEDGE21"] = PRISM21;
650
651 // PYRAMID equivalences
653 element_equivalence_map["PYRAMID5"] = PYRAMID5;
654 element_equivalence_map["PYRAMID13"] = PYRAMID13;
655 element_equivalence_map["PYRAMID14"] = PYRAMID14;
656 element_equivalence_map["PYRAMID18"] = PYRAMID18;
657}

References libMesh::C0POLYGON, libMesh::C0POLYHEDRON, libMesh::EDGE2, libMesh::EDGE3, libMesh::EDGE4, element_equivalence_map, libMesh::HEX20, libMesh::HEX27, libMesh::HEX8, libMesh::NODEELEM, libMesh::PRISM15, libMesh::PRISM18, libMesh::PRISM20, libMesh::PRISM21, libMesh::PRISM6, libMesh::PYRAMID13, libMesh::PYRAMID14, libMesh::PYRAMID18, libMesh::PYRAMID5, libMesh::QUAD4, libMesh::QUAD8, libMesh::QUAD9, libMesh::QUADSHELL4, libMesh::QUADSHELL8, libMesh::QUADSHELL9, libMesh::TET10, libMesh::TET14, libMesh::TET4, libMesh::TRI3, libMesh::TRI6, libMesh::TRI7, and libMesh::TRISHELL3.

Referenced by ExodusII_IO_Helper().

◆ initialize()

void libMesh::ExodusII_IO_Helper::initialize ( std::string  title,
const MeshBase &  mesh,
bool  use_discontinuous = false 
)
virtual

Initializes the Exodus file.

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 2668 of file exodusII_io_helper.C.

2669{
2670 // The majority of this function only executes on processor 0, so any functions
2671 // which are collective, like n_active_elem() or n_edge_conds() must be called
2672 // before the processors' execution paths diverge.
2673 libmesh_parallel_only(mesh.comm());
2674
2675 unsigned int n_active_elem = mesh.n_active_elem();
2676 const BoundaryInfo & bi = mesh.get_boundary_info();
2677 num_edge = bi.n_edge_conds();
2678
2679 num_elem = n_active_elem;
2680 num_nodes = 0;
2681 num_face = 0;
2682 num_face_blk = 0;
2683
2684 dof_id_type local_num_c0polyhedron_faces = 0;
2685 bool has_c0polyhedron = false;
2686 for (const auto & elem : mesh.active_local_element_ptr_range())
2687 if (elem->type() == C0POLYHEDRON)
2688 {
2689 has_c0polyhedron = true;
2690 local_num_c0polyhedron_faces += elem->n_sides();
2691 }
2692
2693 mesh.comm().sum(local_num_c0polyhedron_faces);
2694 mesh.comm().max(has_c0polyhedron);
2695 if (has_c0polyhedron)
2696 {
2697 num_face = cast_int<int>(local_num_c0polyhedron_faces);
2698 num_face_blk = 1;
2699 }
2700
2701 // If we're adding face elements they'll need copies of their nodes.
2702 // We also have to count of how many nodes (and gaps between nodes!)
2703 // are on each processor, to calculate offsets for any nodal data
2704 // writing later.
2706 if (_add_sides)
2707 {
2708 dof_id_type num_side_elem = 0;
2709 dof_id_type num_local_side_nodes = 0;
2710
2711 for (const auto & elem : mesh.active_local_element_ptr_range())
2712 {
2713 for (auto s : elem->side_index_range())
2714 {
2716 continue;
2717
2718 num_side_elem++;
2719 num_local_side_nodes += elem->nodes_on_side(s).size();
2720 }
2721 }
2722
2723 mesh.comm().sum(num_side_elem);
2724 num_elem += num_side_elem;
2725
2726 mesh.comm().allgather(num_local_side_nodes, _added_side_node_offsets);
2727 const processor_id_type n_proc = mesh.n_processors();
2728 libmesh_assert_equal_to(n_proc, _added_side_node_offsets.size());
2729
2730 for (auto p : make_range(n_proc-1))
2732
2734
2735 dof_id_type n_local_nodes = cast_int<dof_id_type>
2736 (std::distance(mesh.local_nodes_begin(),
2737 mesh.local_nodes_end()));
2738 dof_id_type n_total_nodes = n_local_nodes;
2739 mesh.comm().sum(n_total_nodes);
2740
2741 const dof_id_type max_nn = mesh.max_node_id();
2742 const dof_id_type n_gaps = max_nn - n_total_nodes;
2743 const dof_id_type gaps_per_processor = n_gaps / n_proc;
2744 const dof_id_type remainder_gaps = n_gaps % n_proc;
2745
2746 n_local_nodes = n_local_nodes + // Actual nodes
2747 gaps_per_processor + // Our even share of gaps
2748 (mesh.processor_id() < remainder_gaps); // Leftovers
2749
2750 mesh.comm().allgather(n_local_nodes, _true_node_offsets);
2751 for (auto p : make_range(n_proc-1))
2753 libmesh_assert_equal_to(_true_node_offsets[n_proc-1], mesh.max_node_id());
2754 }
2755
2756 // If _write_as_dimension is nonzero, use it to set num_dim in the Exodus file.
2761 else
2763
2764 if ((_run_only_on_proc0) && (this->processor_id() != 0))
2765 return;
2766
2767 // We need to know about all processors' subdomains
2768 subdomain_id_type subdomain_id_end = 0;
2769 auto subdomain_map = build_subdomain_map(mesh,
2770 _add_sides,
2771 /*reduce=*/!_run_only_on_proc0,
2772 subdomain_id_end);
2773
2774 if (!use_discontinuous)
2775 {
2776 // Don't rely on mesh.n_nodes() here. If ReplicatedMesh nodes
2777 // have been deleted without renumbering after, it will be
2778 // incorrect.
2779 num_nodes += cast_int<int>(std::distance(mesh.nodes_begin(),
2780 mesh.nodes_end()));
2781 }
2782 else
2783 {
2784 for (const auto & elem : mesh.active_element_ptr_range())
2785 num_nodes += elem->n_nodes();
2786 }
2787
2788 std::set<boundary_id_type> unique_side_boundaries;
2789 std::vector<boundary_id_type> unique_node_boundaries;
2790
2791 // Build set of unique sideset (+shellface) ids
2792 {
2793 // Start with "side" boundaries (i.e. of 3D elements)
2794 std::vector<boundary_id_type> side_boundaries;
2795 bi.build_side_boundary_ids(side_boundaries);
2796 unique_side_boundaries.insert(side_boundaries.begin(), side_boundaries.end());
2797
2798 // Add shell face boundaries to the list of side boundaries, since ExodusII
2799 // treats these the same way.
2800 std::vector<boundary_id_type> shellface_boundaries;
2801 bi.build_shellface_boundary_ids(shellface_boundaries);
2802 unique_side_boundaries.insert(shellface_boundaries.begin(), shellface_boundaries.end());
2803
2804 // Add any empty-but-named side boundary ids
2805 for (const auto & pr : bi.get_sideset_name_map())
2806 unique_side_boundaries.insert(pr.first);
2807 }
2808
2809 // Build set of unique nodeset ids
2810 bi.build_node_boundary_ids(unique_node_boundaries);
2811 for (const auto & pair : bi.get_nodeset_name_map())
2812 {
2813 const boundary_id_type id = pair.first;
2814
2815 if (std::find(unique_node_boundaries.begin(),
2816 unique_node_boundaries.end(), id)
2817 == unique_node_boundaries.end())
2818 unique_node_boundaries.push_back(id);
2819 }
2820
2821 num_side_sets = cast_int<int>(unique_side_boundaries.size());
2822 num_node_sets = cast_int<int>(unique_node_boundaries.size());
2823
2824 num_elem_blk = cast_int<int>(subdomain_map.size());
2825
2826 if (str_title.size() > MAX_LINE_LENGTH)
2827 {
2828 libMesh::err << "Warning, Exodus files cannot have titles longer than "
2829 << MAX_LINE_LENGTH
2830 << " characters. Your title will be truncated."
2831 << std::endl;
2832 str_title.resize(MAX_LINE_LENGTH);
2833 }
2834
2835 // Edge BCs are handled a bit differently than sidesets and nodesets.
2836 // They are written as separate "edge blocks", and then edge variables
2837 // can be defined on those blocks. That is, they are not written as
2838 // edge sets, since edge sets must refer to edges stored elsewhere.
2839 // We write a separate edge block for each unique boundary id that
2840 // we have.
2841 num_edge_blk = bi.get_edge_boundary_ids().size();
2842
2843 // Check whether the Mesh Elems have an extra_integer called "elemset_code".
2844 // If so, this means that the mesh defines elemsets via the
2845 // extra_integers capability of Elems.
2846 if (mesh.has_elem_integer("elemset_code"))
2847 {
2848 // unsigned int elemset_index =
2849 // mesh.get_elem_integer_index("elemset_code");
2850
2851 // Debugging
2852 // libMesh::out << "Mesh defines an elemset_code at index " << elemset_index << std::endl;
2853
2854 // Store the number of elemsets in the exo file header.
2856 }
2857
2858 // Build an ex_init_params() structure that is to be passed to the
2859 // newer ex_put_init_ext() API. The new API will eventually allow us
2860 // to store edge and face data in the Exodus file.
2861 //
2862 // Notes:
2863 // * We use C++11 zero initialization syntax to make sure that all
2864 // members of the struct (including ones we aren't using) are
2865 // given sensible values.
2866 // * For the "title" field, we manually do a null-terminated string
2867 // copy since std::string does not null-terminate but it does
2868 // return the number of characters successfully copied.
2869 exII::ex_init_params params = {};
2870 params.title[str_title.copy(params.title, MAX_LINE_LENGTH)] = '\0';
2871 params.num_dim = num_dim;
2872 params.num_nodes = num_nodes;
2873 params.num_elem = num_elem;
2874 params.num_elem_blk = num_elem_blk;
2875 params.num_node_sets = num_node_sets;
2876 params.num_side_sets = num_side_sets;
2877 params.num_elem_sets = num_elem_sets;
2878 params.num_edge_blk = num_edge_blk;
2879 params.num_edge = num_edge;
2880 params.num_face_blk = num_face_blk;
2881 params.num_face = num_face;
2882
2883 ex_err = exII::ex_put_init_ext(ex_id, &params);
2884 EX_CHECK_ERR(ex_err, "Error initializing new Exodus file.");
2885}
void max(const T &r, T &o, Request &req) const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
std::size_t n_edge_conds() const
const std::set< boundary_id_type > & get_edge_boundary_ids() const
void build_node_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique node boundary ids.
void build_side_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique side boundary ids.
void build_shellface_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique shellface boundary ids.
static bool redundant_added_side(const Elem &elem, unsigned int side)
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
unsigned int mesh_dimension() const
Definition mesh_base.C:435
unsigned int spatial_dimension() const
Definition mesh_base.h:2682
virtual dof_id_type max_node_id() const =0
bool has_elem_integer(std::string_view name) const
Definition mesh_base.C:701
unsigned int n_elemsets() const
Returns the number of unique elemset ids which have been added via add_elemset_code(),...
Definition mesh_base.C:487
virtual dof_id_type n_active_elem() const =0
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
int8_t boundary_id_type
Definition id_types.h:51
uint8_t processor_id_type
Definition id_types.h:104
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176
const dof_id_type n_nodes
Definition tecplot_io.C:67

References _add_sides, _added_side_node_offsets, _run_only_on_proc0, _true_node_offsets, _use_mesh_dimension_instead_of_spatial_dimension, _write_as_dimension, libMesh::Parallel::Communicator::allgather(), libMesh::BoundaryInfo::build_node_boundary_ids(), libMesh::BoundaryInfo::build_shellface_boundary_ids(), libMesh::BoundaryInfo::build_side_boundary_ids(), libMesh::C0POLYHEDRON, libMesh::ParallelObject::comm(), libMesh::err, ex_err, ex_id, libMesh::MeshBase::get_boundary_info(), libMesh::BoundaryInfo::get_edge_boundary_ids(), libMesh::BoundaryInfo::get_nodeset_name_map(), libMesh::BoundaryInfo::get_sideset_name_map(), libMesh::MeshBase::has_elem_integer(), libMesh::make_range(), libMesh::Parallel::Communicator::max(), libMesh::MeshBase::max_node_id(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_active_elem(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::MeshBase::n_elemsets(), libMesh::Elem::n_nodes(), libMesh::ParallelObject::n_processors(), libMesh::Elem::n_sides(), libMesh::Elem::nodes_on_side(), num_dim, num_edge, num_edge_blk, num_elem, num_elem_blk, num_elem_sets, num_face, num_face_blk, num_node_sets, num_nodes, num_side_sets, libMesh::ParallelObject::processor_id(), libMesh::EquationSystems::redundant_added_side(), libMesh::Elem::side_index_range(), libMesh::MeshBase::spatial_dimension(), libMesh::Parallel::Communicator::sum(), and libMesh::Elem::type().

Referenced by ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl().

◆ initialize_element_variables()

void libMesh::ExodusII_IO_Helper::initialize_element_variables ( std::vector< std::string >  names,
const std::vector< std::set< subdomain_id_type > > &  vars_active_subdomains 
)
virtual

Sets up the nodal variables.

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 4028 of file exodusII_io_helper.C.

4030{
4031 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4032 return;
4033
4034 // Quick return if there are no element variables to write
4035 if (names.size() == 0)
4036 return;
4037
4038 // Be sure that variables in the file match what we are asking for
4039 if (num_elem_vars > 0)
4040 {
4041 this->check_existing_vars(ELEMENTAL, names, this->elem_var_names);
4042 return;
4043 }
4044
4045 // Quick return if we have already called this function
4047 return;
4048
4049 // Set the flag so we can skip this stuff on subsequent calls to
4050 // initialize_element_variables()
4052
4053 this->write_var_names(ELEMENTAL, names);
4054
4055 // Use the truth table to indicate which subdomain/variable pairs are
4056 // active according to vars_active_subdomains.
4057 std::vector<int> truth_tab(num_elem_blk*num_elem_vars, 0);
4058 for (auto var_num : index_range(vars_active_subdomains))
4059 {
4060 // If the list of active subdomains is empty, it is interpreted as being
4061 // active on *all* subdomains.
4062 std::set<subdomain_id_type> current_set;
4063 if (vars_active_subdomains[var_num].empty())
4064 for (auto block_id : block_ids)
4065 current_set.insert(restrict_int<subdomain_id_type>(block_id));
4066 else
4067 current_set = vars_active_subdomains[var_num];
4068
4069 // Find index into the truth table for each id in current_set.
4070 for (auto block_id : current_set)
4071 {
4072 auto it = std::find(block_ids.begin(), block_ids.end(), block_id);
4073 libmesh_error_msg_if(it == block_ids.end(),
4074 "ExodusII_IO_Helper: block id " << block_id << " not found in block_ids.");
4075
4076 std::size_t block_index =
4077 std::distance(block_ids.begin(), it);
4078
4079 std::size_t truth_tab_index = block_index*num_elem_vars + var_num;
4080 truth_tab[truth_tab_index] = 1;
4081 }
4082 }
4083
4084 ex_err = exII::ex_put_truth_table
4085 (ex_id,
4086 exII::EX_ELEM_BLOCK,
4089 truth_tab.data());
4090 EX_CHECK_ERR(ex_err, "Error writing element truth table.");
4091}
void write_var_names(ExodusVarType type, const std::vector< std::string > &names)
Wraps calls to exII::ex_put_var_names() and exII::ex_put_var_param().
std::vector< std::string > elem_var_names
void check_existing_vars(ExodusVarType type, std::vector< std::string > &names, std::vector< std::string > &names_from_file)
When appending: during initialization, check that variable names in the file match those you attempt ...
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
Tnew restrict_int(Told oldvar)
restrict_int checks that the value of the castee is within the bounds which are exactly representable...

References _elem_vars_initialized, _run_only_on_proc0, block_ids, check_existing_vars(), elem_var_names, ELEMENTAL, ex_err, ex_id, libMesh::index_range(), num_elem_blk, num_elem_vars, libMesh::ParallelObject::processor_id(), and write_var_names().

◆ initialize_global_variables()

void libMesh::ExodusII_IO_Helper::initialize_global_variables ( std::vector< std::string >  names)

Sets up the global variables.

Definition at line 4123 of file exodusII_io_helper.C.

4124{
4125 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4126 return;
4127
4128 // Quick return if there are no global variables to write
4129 if (names.size() == 0)
4130 return;
4131
4133 return;
4134
4135 // Be sure that variables in the file match what we are asking for
4136 if (num_global_vars > 0)
4137 {
4138 this->check_existing_vars(GLOBAL, names, this->global_var_names);
4139 return;
4140 }
4141
4143
4144 this->write_var_names(GLOBAL, names);
4145}
std::vector< std::string > global_var_names

References _global_vars_initialized, _run_only_on_proc0, check_existing_vars(), GLOBAL, global_var_names, num_global_vars, libMesh::ParallelObject::processor_id(), and write_var_names().

◆ initialize_nodal_variables()

void libMesh::ExodusII_IO_Helper::initialize_nodal_variables ( std::vector< std::string >  names)

Sets up the nodal variables.

Definition at line 4095 of file exodusII_io_helper.C.

4096{
4097 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4098 return;
4099
4100 // Quick return if there are no nodal variables to write
4101 if (names.size() == 0)
4102 return;
4103
4104 // Quick return if we have already called this function
4106 return;
4107
4108 // Be sure that variables in the file match what we are asking for
4109 if (num_nodal_vars > 0)
4110 {
4111 this->check_existing_vars(NODAL, names, this->nodal_var_names);
4112 return;
4113 }
4114
4115 // Set the flag so we can skip the rest of this function on subsequent calls.
4117
4118 this->write_var_names(NODAL, names);
4119}
std::vector< std::string > nodal_var_names

References _nodal_vars_initialized, _run_only_on_proc0, check_existing_vars(), NODAL, nodal_var_names, num_nodal_vars, libMesh::ParallelObject::processor_id(), and write_var_names().

◆ message() [1/2]

void libMesh::ExodusII_IO_Helper::message ( std::string_view  msg)

◆ message() [2/2]

void libMesh::ExodusII_IO_Helper::message ( std::string_view  msg,
int  i 
)

Prints the message defined in msg, and appends the number i to the end of the message.

Useful for printing messages in loops. Can be turned off if verbosity is set to 0.

Definition at line 688 of file exodusII_io_helper.C.

689{
690 if (verbose) libMesh::out << msg << i << "." << std::endl;
691}

References libMesh::out, and verbose.

◆ n_processors()

processor_id_type libMesh::ParallelObject::n_processors ( ) const
inlineinherited
Returns
The number of processors in the group.

Definition at line 103 of file parallel_object.h.

104 {
105 processor_id_type returnval =
106 cast_int<processor_id_type>(_communicator.size());
107 libmesh_assert(returnval); // We never have an empty comm
108 return returnval;
109 }
processor_id_type size() const

References libMesh::ParallelObject::_communicator, libMesh::libmesh_assert(), and libMesh::Parallel::Communicator::size().

Referenced by libMesh::Partitioner::_find_global_index_by_pid_map(), libMesh::BoundaryInfo::_find_id_maps(), libMesh::DofMap::add_constraints_to_send_list(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::DistributedMesh::add_node(), libMesh::System::add_vector(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::FEMSystem::assembly(), ExodusC0PolyhedronTest::assert_distributed_if_parallel(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::Partitioner::build_graph(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::copy_nodes_and_elements(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::UnstructuredMesh::create_pid_mesh(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::EnsightIO::EnsightIO(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::MeshBase::get_info(), libMesh::StaticCondensation::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_petscdm(), initialize(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::DistributedMesh::insert_elem(), libMesh::NumericVector< T >::is_effectively_ghosted(), libMesh::NumericVector< T >::is_effectively_serial(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshBase::n_active_elem_on_proc(), libMesh::DofMap::n_dofs_per_processor(), libMesh::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::MeshBase::partition(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::CheckpointIO::read_connectivity(), libMesh::XdrIO::read_header(), libMesh::CheckpointIO::read_nodes(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::System::read_serialized_vector(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::Partitioner::repartition(), OverlappingFunctorTest::run_partitioner_test(), libMesh::DofMap::scatter_constraints(), libMesh::DistributedMesh::set_next_ids(), libMesh::DistributedMesh::set_next_unique_id(), libMesh::DistributedMesh::set_next_unique_ids(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), WriteVecAndScalar::setupTests(), libMesh::RBEIMEvaluation::side_gather_bfs(), ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl(), CheckpointIOTest::testDisjointNeighborPairsCheckpoint(), DistributedMeshTest::testRemoteElemError(), CheckpointIOTest::testSplitter(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), write_nodal_coordinates(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

◆ node_id_to_vec_id()

dof_id_type libMesh::ExodusII_IO_Helper::node_id_to_vec_id ( dof_id_type  n) const
inline

Definition at line 966 of file exodusII_io_helper.h.

967 {
968 if (_added_side_node_offsets.empty())
969 return n;
970
971 // Find the processor id that has node_id in the parallel vec
972 const auto lb = std::upper_bound(_true_node_offsets.begin(),
973 _true_node_offsets.end(), n);
975 const processor_id_type p = lb - _true_node_offsets.begin();
976
977 return n + (p ? _added_side_node_offsets[p-1] : 0);
978 }

References _added_side_node_offsets, _true_node_offsets, and libMesh::libmesh_assert().

◆ open()

void libMesh::ExodusII_IO_Helper::open ( const char *  filename,
bool  read_only 
)

Opens an ExodusII mesh file named filename.

If read_only==true, the file will be opened with the EX_READ flag, otherwise it will be opened with the EX_WRITE flag.

Definition at line 780 of file exodusII_io_helper.C.

781{
782 // Version of Exodus you are using
783 float ex_version = 0.;
784
785 int comp_ws = 0;
786
788 comp_ws = cast_int<int>(sizeof(float));
789
790 // Fall back on double precision when necessary since ExodusII
791 // doesn't seem to support long double
792 else
793 comp_ws = cast_int<int>(std::min(sizeof(Real), sizeof(double)));
794
795 // Word size in bytes of the floating point data as they are stored
796 // in the ExodusII file. "If this argument is 0, the word size of the
797 // floating point data already stored in the file is returned"
798 int io_ws = 0;
799
800 {
801 FPEDisabler disable_fpes;
802 ex_id = exII::ex_open(filename,
803 read_only ? EX_READ : EX_WRITE,
804 &comp_ws,
805 &io_ws,
806 &ex_version);
807 }
808
809 std::string err_msg = std::string("Error opening ExodusII mesh file: ") + std::string(filename);
810 EX_CHECK_ERR(ex_id, err_msg);
811 if (verbose) libMesh::out << "File opened successfully." << std::endl;
812
813 // If we're writing then we'll want to use the specified length;
814 // if we're reading then we'll override this by what's in the file.
815 int max_name_length_to_set = _max_name_length;
816
817 if (read_only)
818 {
819 opened_for_reading = true;
820 elem_node_counts.clear();
821 elem_face_counts.clear();
823
824 // ExodusII reads truncate to 32-char strings by default; we'd
825 // like to support whatever's in the file, so as early as possible
826 // let's find out what that is.
827 int max_name_length = exII::ex_inquire_int(ex_id, exII::EX_INQ_DB_MAX_USED_NAME_LENGTH);
828
829 libmesh_error_msg_if(max_name_length > MAX_LINE_LENGTH,
830 "Unexpected maximum name length of " <<
831 max_name_length << " in file " << filename <<
832 " exceeds expected " << MAX_LINE_LENGTH);
833
834 // I don't think the 32 here should be necessary, but let's make
835 // sure we don't accidentally make things *worse* for anyone.
836 max_name_length_to_set = std::max(max_name_length, 32);
837 }
838 else
839 opened_for_writing = true;
840
841 ex_err = exII::ex_set_max_name_length(ex_id, max_name_length_to_set);
842 EX_CHECK_ERR(ex_err, "Error setting max ExodusII name length.");
843
844 current_filename = std::string(filename);
845}
std::vector< int > elem_face_counts
std::vector< std::vector< int > > c0polyhedron_face_connect
std::vector< int > elem_node_counts

References _max_name_length, _single_precision, c0polyhedron_face_connect, current_filename, elem_face_counts, elem_node_counts, ex_err, ex_id, opened_for_reading, opened_for_writing, libMesh::out, libMesh::Real, and verbose.

◆ operator=() [1/2]

ExodusII_IO_Helper & libMesh::ExodusII_IO_Helper::operator= ( const ExodusII_IO_Helper &  )
delete

This class contains references so it can't be default copy/move-assigned.

◆ operator=() [2/2]

ExodusII_IO_Helper & libMesh::ExodusII_IO_Helper::operator= ( ExodusII_IO_Helper &&  )
delete

◆ print_header()

void libMesh::ExodusII_IO_Helper::print_header ( )

Prints the ExodusII mesh file header, which includes the mesh title, the number of nodes, number of elements, mesh dimension, number of sidesets, and number of nodesets.

Definition at line 977 of file exodusII_io_helper.C.

978{
979 if (verbose)
980 libMesh::out << "Title: \t" << title.data() << std::endl
981 << "Mesh Dimension: \t" << num_dim << std::endl
982 << "Number of Nodes: \t" << num_nodes << std::endl
983 << "Number of elements: \t" << num_elem << std::endl
984 << "Number of elt blocks: \t" << num_elem_blk << std::endl
985 << "Number of node sets: \t" << num_node_sets << std::endl
986 << "Number of side sets: \t" << num_side_sets << std::endl
987 << "Number of elem sets: \t" << num_elem_sets << std::endl;
988}

References num_dim, num_elem, num_elem_blk, num_elem_sets, num_node_sets, num_nodes, num_side_sets, libMesh::out, title, and verbose.

◆ print_nodes()

void libMesh::ExodusII_IO_Helper::print_nodes ( std::ostream &  out_stream = libMesh::out)

Prints the nodal information, by default to libMesh::out.

Definition at line 1179 of file exodusII_io_helper.C.

1180{
1181 for (int i=0; i<num_nodes; i++)
1182 out_stream << "(" << x[i] << ", " << y[i] << ", " << z[i] << ")" << std::endl;
1183}

References num_nodes, x, y, and z.

◆ processor_id()

processor_id_type libMesh::ParallelObject::processor_id ( ) const
inlineinherited
Returns
The rank of this processor in the group.

Definition at line 114 of file parallel_object.h.

115 { return cast_int<processor_id_type>(_communicator.rank()); }
processor_id_type rank() const

References libMesh::ParallelObject::_communicator, and libMesh::Parallel::Communicator::rank().

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::BoundaryInfo::add_elements(), libMesh::DistributedMesh::add_node(), libMesh::MeshTools::Modification::all_tri(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::MeshFunction::check_found_elem(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), close(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::compute_communication_map_parameters(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_node_communication_maps(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshBase::count_constraint_rows(), create(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DofMapBase::end_dof(), libMesh::DofMapBase::end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::find_dofs_to_send(), libMesh::UnstructuredMesh::find_neighbors(), libMesh::DofMapBase::first_dof(), libMesh::DofMapBase::first_old_dof(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::MeshBase::get_info(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), libMesh::DofMap::get_local_constraints(), libMesh::MeshBase::get_local_constraints(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::LaplaceMeshSmoother::init(), libMesh::SystemSubsetBySubdomain::init(), HeatSystem::init_data(), initialize(), initialize_element_variables(), initialize_global_variables(), initialize_nodal_variables(), libMesh::DistributedMesh::insert_elem(), libMesh::MeshTools::Modification::interpolate_surface(), libMesh::SparsityPattern::Build::join(), libMesh::RBEvaluation::legacy_write_offline_data_to_files(), libMesh::RBSCMEvaluation::legacy_write_offline_data_to_files(), libMesh::TransientRBEvaluation::legacy_write_offline_data_to_files(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), main(), AugmentSparsityOnInterface::mesh_reinit(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), libMesh::MeshBase::n_active_local_elem(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::DofMapBase::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::DistributedMesh::own_node(), libMesh::BoundaryInfo::parallel_sync_node_ids(), libMesh::BoundaryInfo::parallel_sync_side_ids(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::DofMap::process_mesh_constraint_rows(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::XdrIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::EquationSystems::read(), libMesh::EquationSystems::read(), read_elem_num_map(), read_global_values(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::DynaIO::read_mesh(), read_node_num_map(), libMesh::System::read_parallel_data(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::System::read_serialized_data(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::System::read_serialized_vectors(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), libMesh::DofMap::scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::DistributedMesh::set_next_ids(), libMesh::DistributedMesh::set_next_unique_id(), libMesh::DistributedMesh::set_next_unique_ids(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::RBEIMEvaluation::side_gather_bfs(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), ExodusTest< elem_type >::test_read_gold(), ExodusTest< elem_type >::test_write(), ExodusC0PolyhedronTest::test_write_and_read_hexagonal_prism(), ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl(), ExodusC0PolygonTest::test_write_and_read_pentagon(), MeshInputTest::testAbaqusRead(), MeshInputTest::testBadGmsh(), BoundaryInfoTest::testBoundaryIDs(), MeshInputTest::testCopyElementSolutionImpl(), MeshInputTest::testCopyElementVectorImpl(), MeshInputTest::testCopyNodalSolutionImpl(), DefaultCouplingTest::testCoupling(), PointNeighborCouplingTest::testCoupling(), MeshInputTest::testDynaFileMappings(), MeshInputTest::testDynaNoSplines(), MeshInputTest::testDynaReadElem(), MeshInputTest::testDynaReadPatch(), MeshInputTest::testExodusCopyHighOrderElementSolution(), MeshInputTest::testExodusFileMappings(), MeshInputTest::testExodusIGASidesets(), MeshInputTest::testExodusWriteElementDataFromDiscontinuousNodalData(), DofMapTest::testGhostConstraintSendList(), MeshInputTest::testGmshBCIDOverlap(), MeshInputTest::testGoodGmsh(), MeshInputTest::testGoodSTL(), MeshInputTest::testGoodSTLBinary(), BoundaryInfoTest::testInternalBoundary(), MeshInputTest::testLowOrderEdgeBlocks(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), SystemsTest::testProjectMatrix3D(), BoundaryInfoTest::testShellFaceConstraints(), MeshInputTest::testSingleElementImpl(), BoundaryMeshSubdomainTest::testSingleSubdomain(), WriteVecAndScalar::testSolution(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::NetGenMeshInterface::triangulate(), libMesh::Parallel::Packing< Elem * >::unpack(), libMesh::Parallel::Packing< Node * >::unpack(), libMesh::DTKAdapter::update_variable_values(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::XdrIO::write(), libMesh::NameBasedIO::write(), libMesh::CheckpointIO::write(), libMesh::EquationSystems::write(), libMesh::EquationSystems::write(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::ExodusII_IO::write_element_data_from_discontinuous_nodal_data(), write_element_values(), write_element_values_element_major(), write_elements(), write_elemset_data(), write_elemsets(), libMesh::ExodusII_IO::write_global_data(), write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), write_information_records(), write_nodal_coordinates(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::UCDIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_common(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), write_nodal_values(), write_nodeset_data(), write_nodesets(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), write_output_solvedata(), libMesh::System::write_parallel_data(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bc_names(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::System::write_serialized_data(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::System::write_serialized_vector(), libMesh::System::write_serialized_vectors(), write_sideset_data(), write_sidesets(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), write_timestep(), and libMesh::ExodusII_IO::write_timestep_discontinuous().

◆ read_all_nodesets()

void libMesh::ExodusII_IO_Helper::read_all_nodesets ( )

New API that reads all nodesets simultaneously.

This may be slightly faster than reading them one at a time. Calls ex_get_concat_node_sets() under the hood.

Definition at line 2058 of file exodusII_io_helper.C.

2059{
2060 LOG_SCOPE("read_all_nodesets()", "ExodusII_IO_Helper");
2061
2062 // Figure out how many nodesets there are in the file so we can
2063 // properly resize storage as necessary.
2065 inquire
2066 (*this, exII::EX_INQ_NODE_SETS,
2067 "Error retrieving number of node sets");
2068
2069 // Figure out how many nodes there are in all the nodesets.
2070 int total_nodes_in_all_sets =
2071 inquire
2072 (*this, exII::EX_INQ_NS_NODE_LEN,
2073 "Error retrieving number of nodes in all node sets.");
2074
2075 // Figure out how many distribution factors there are in all the nodesets.
2076 int total_df_in_all_sets =
2077 inquire
2078 (*this, exII::EX_INQ_NS_DF_LEN,
2079 "Error retrieving number of distribution factors in all node sets.");
2080
2081 // If there are no nodesets, there's nothing to read in.
2082 if (num_node_sets == 0)
2083 return;
2084
2085 // Allocate space to read all the nodeset data.
2086 // Use existing class members where possible to avoid shadowing
2087 nodeset_ids.clear(); nodeset_ids.resize(num_node_sets);
2092 node_sets_node_list.clear(); node_sets_node_list.resize(total_nodes_in_all_sets);
2093 node_sets_dist_fact.clear(); node_sets_dist_fact.resize(total_df_in_all_sets);
2094
2095 // Handle single-precision files
2096 MappedInputVector mapped_node_sets_dist_fact(node_sets_dist_fact, _single_precision);
2097
2098 // Build exII::ex_set_spec struct
2099 exII::ex_set_specs set_specs = {};
2100 set_specs.sets_ids = nodeset_ids.data();
2101 set_specs.num_entries_per_set = num_nodes_per_set.data();
2102 set_specs.num_dist_per_set = num_node_df_per_set.data();
2103 set_specs.sets_entry_index = node_sets_node_index.data();
2104 set_specs.sets_dist_index = node_sets_dist_index.data();
2105 set_specs.sets_entry_list = node_sets_node_list.data();
2106 set_specs.sets_extra_list = nullptr;
2107 set_specs.sets_dist_fact = total_df_in_all_sets ? mapped_node_sets_dist_fact.data() : nullptr;
2108
2109 ex_err = exII::ex_get_concat_sets(ex_id, exII::EX_NODE_SET, &set_specs);
2110 EX_CHECK_ERR(ex_err, "Error reading concatenated nodesets");
2111
2112 // Read the nodeset names from file!
2113 char name_buffer[libmesh_max_str_length+1];
2114 for (int i=0; i<num_node_sets; ++i)
2115 {
2116 ex_err = exII::ex_get_name
2117 (ex_id,
2118 exII::EX_NODE_SET,
2119 nodeset_ids[i],
2120 name_buffer);
2121 EX_CHECK_ERR(ex_err, "Error getting node set name.");
2122 id_to_ns_names[nodeset_ids[i]] = name_buffer;
2123 }
2124}
std::vector< int > node_sets_dist_index
std::vector< int > node_sets_node_index
std::vector< int > num_node_df_per_set
std::vector< Real > node_sets_dist_fact

References _single_precision, libMesh::ExodusII_IO_Helper::MappedInputVector::data(), ex_err, ex_id, id_to_ns_names, node_sets_dist_fact, node_sets_dist_index, node_sets_node_index, node_sets_node_list, nodeset_ids, num_node_df_per_set, num_node_sets, and num_nodes_per_set.

Referenced by write_nodeset_data().

◆ read_and_store_header_info()

void libMesh::ExodusII_IO_Helper::read_and_store_header_info ( )

Reads an ExodusII mesh file header, and stores required information on this object.

Definition at line 882 of file exodusII_io_helper.C.

883{
884 // Read header params from file, storing them in this class's
885 // ExodusHeaderInfo struct. This automatically updates the local
886 // num_dim, num_elem, etc. references.
887 this->header_info = this->read_header();
888
889 // Read the number of timesteps which are present in the file
890 this->read_num_time_steps();
891
892 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_NODAL, &num_nodal_vars);
893 EX_CHECK_ERR(ex_err, "Error reading number of nodal variables.");
894
895 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_BLOCK, &num_elem_vars);
896 EX_CHECK_ERR(ex_err, "Error reading number of elemental variables.");
897
898 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_GLOBAL, &num_global_vars);
899 EX_CHECK_ERR(ex_err, "Error reading number of global variables.");
900
901 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_SIDE_SET, &num_sideset_vars);
902 EX_CHECK_ERR(ex_err, "Error reading number of sideset variables.");
903
904 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_NODE_SET, &num_nodeset_vars);
905 EX_CHECK_ERR(ex_err, "Error reading number of nodeset variables.");
906
907 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_SET, &num_elemset_vars);
908 EX_CHECK_ERR(ex_err, "Error reading number of elemset variables.");
909
910 message("Exodus header info retrieved successfully.");
911}
ExodusHeaderInfo read_header() const
Reads an ExodusII mesh file header, leaving this object's internal data structures unchanged.
void read_num_time_steps()
Reads the number of timesteps currently stored in the Exodus file and stores it in the num_time_steps...

References ex_err, ex_id, header_info, message(), num_elem_vars, num_elemset_vars, num_global_vars, num_nodal_vars, num_nodeset_vars, num_sideset_vars, read_header(), and read_num_time_steps().

◆ read_bex_cv_blocks()

void libMesh::ExodusII_IO_Helper::read_bex_cv_blocks ( )

Reads the optional bex_cv_blocks from the ExodusII mesh file.

Definition at line 1067 of file exodusII_io_helper.C.

1068{
1069 // If a bex blob exists, we look for Bezier Extraction coefficient
1070 // data there.
1071
1072 // These APIs require newer Exodus than 5.22
1073#if EX_API_VERS_NODOT >= 800
1074 int n_blobs = exII::ex_inquire_int(ex_id, exII::EX_INQ_BLOB);
1075
1076 if (n_blobs > 0)
1077 {
1078 std::vector<exII::ex_blob> blobs(n_blobs);
1079 std::vector<std::vector<char>> blob_names(n_blobs);
1080 for (auto i : make_range(n_blobs))
1081 {
1082 blob_names[i].resize(libmesh_max_str_length+1);
1083 blobs[i].name = blob_names[i].data();
1084 }
1085
1086 ex_err = exII::ex_get_blobs(ex_id, blobs.data());
1087 EX_CHECK_ERR(ex_err, "Error getting blobs.");
1088
1089 bool found_blob = false;
1090 const exII::ex_blob * my_blob = &blobs[0];
1091 for (const auto & blob : blobs)
1092 {
1093 if (std::string("bex_cv_blob") == blob.name)
1094 {
1095 found_blob = true;
1096 my_blob = &blob;
1097 }
1098 }
1099
1100 if (!found_blob)
1101 libmesh_error_msg("Found no bex_cv_blob for bezier elements");
1102
1103 const int n_blob_attr =
1104 exII::ex_get_attribute_count(ex_id, exII::EX_BLOB,
1105 my_blob->id);
1106
1107 std::vector<exII::ex_attribute> attributes(n_blob_attr);
1108 ex_err = exII::ex_get_attribute_param(ex_id, exII::EX_BLOB,
1109 my_blob->id,
1110 attributes.data());
1111 EX_CHECK_ERR(ex_err, "Error getting bex blob attribute parameters.");
1112
1113 int bex_num_dense_cv_blocks = 0;
1114 std::vector<int> bex_dense_cv_info;
1115 for (auto & attr : attributes)
1116 {
1117 if (std::string("bex_dense_cv_info") == attr.name)
1118 {
1119 const std::size_t value_count = attr.value_count;
1120 if (value_count % 2)
1121 libmesh_error_msg("Found odd number of bex_dense_cv_info");
1122
1123 bex_dense_cv_info.resize(value_count);
1124 attr.values = bex_dense_cv_info.data();
1125 exII::ex_get_attribute(ex_id, &attr);
1126
1127 bex_num_dense_cv_blocks = value_count / 2;
1128
1129 libmesh_error_msg_if(bex_num_dense_cv_blocks > 1,
1130 "Found more than 1 dense bex CV block; unsure how to handle that");
1131 }
1132 }
1133
1134 if (bex_dense_cv_info.empty())
1135 libmesh_error_msg("No bex_dense_cv_info found");
1136
1137 int n_blob_vars;
1138 exII::ex_get_variable_param(ex_id, exII::EX_BLOB, &n_blob_vars);
1139 std::vector<char> var_name (libmesh_max_str_length + 1);
1140 for (auto v_id : make_range(1,n_blob_vars+1))
1141 {
1142 ex_err = exII::ex_get_variable_name(ex_id, exII::EX_BLOB, v_id, var_name.data());
1143 EX_CHECK_ERR(ex_err, "Error reading bex blob var name.");
1144
1145 if (std::string("bex_dense_cv_blocks") == var_name.data())
1146 {
1147 std::vector<double> bex_dense_cv_blocks(my_blob->num_entry);
1148
1149 ex_err = exII::ex_get_var(ex_id, 1, exII::EX_BLOB, v_id,
1150 my_blob->id, my_blob->num_entry,
1151 bex_dense_cv_blocks.data());
1152 EX_CHECK_ERR(ex_err, "Error reading bex_dense_cv_blocks.");
1153
1155 bex_dense_constraint_vecs.resize(bex_num_dense_cv_blocks);
1156
1157 std::size_t offset = 0;
1158 for (auto i : IntRange<std::size_t>(0, bex_num_dense_cv_blocks))
1159 {
1160 bex_dense_constraint_vecs[i].resize(bex_dense_cv_info[2*i]);
1161 const int vecsize = bex_dense_cv_info[2*i+1];
1162 for (auto & vec : bex_dense_constraint_vecs[i])
1163 {
1164 vec.resize(vecsize);
1165 std::copy(std::next(bex_dense_cv_blocks.begin(), offset),
1166 std::next(bex_dense_cv_blocks.begin(), offset + vecsize),
1167 vec.begin());
1168 offset += vecsize;
1169 }
1170 }
1171 libmesh_assert(offset == bex_dense_cv_blocks.size());
1172 }
1173 }
1174 }
1175#endif // EX_API_VERS_NODOT >= 800
1176}
std::vector< std::vector< std::vector< Real > > > bex_dense_constraint_vecs
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition int_range.h:54

References bex_dense_constraint_vecs, ex_err, ex_id, libMesh::libmesh_assert(), and libMesh::make_range().

◆ read_block_info()

void libMesh::ExodusII_IO_Helper::read_block_info ( )

Reads information for all of the blocks in the ExodusII mesh file.

Definition at line 1187 of file exodusII_io_helper.C.

1188{
1189 if (num_elem_blk)
1190 {
1191 // Read all element block IDs.
1192 block_ids.resize(num_elem_blk);
1193 ex_err = exII::ex_get_ids(ex_id,
1194 exII::EX_ELEM_BLOCK,
1195 block_ids.data());
1196
1197 EX_CHECK_ERR(ex_err, "Error getting block IDs.");
1198 message("All block IDs retrieved successfully.");
1199
1200 char name_buffer[libmesh_max_str_length+1];
1201 for (int i=0; i<num_elem_blk; ++i)
1202 {
1203 ex_err = exII::ex_get_name(ex_id, exII::EX_ELEM_BLOCK,
1204 block_ids[i], name_buffer);
1205 EX_CHECK_ERR(ex_err, "Error getting block name.");
1206 id_to_block_names[block_ids[i]] = name_buffer;
1207 }
1208 message("All block names retrieved successfully.");
1209 }
1210
1211 if (num_edge_blk)
1212 {
1213 // Read all edge block IDs.
1215 ex_err = exII::ex_get_ids(ex_id,
1216 exII::EX_EDGE_BLOCK,
1217 edge_block_ids.data());
1218
1219 EX_CHECK_ERR(ex_err, "Error getting edge block IDs.");
1220 message("All edge block IDs retrieved successfully.");
1221
1222 // Read in edge block names
1223 char name_buffer[libmesh_max_str_length+1];
1224 for (int i=0; i<num_edge_blk; ++i)
1225 {
1226 ex_err = exII::ex_get_name(ex_id, exII::EX_EDGE_BLOCK,
1227 edge_block_ids[i], name_buffer);
1228 EX_CHECK_ERR(ex_err, "Error getting block name.");
1229 id_to_edge_block_names[edge_block_ids[i]] = name_buffer;
1230 }
1231 message("All edge block names retrieved successfully.");
1232 }
1233}
std::map< int, std::string > id_to_edge_block_names

References block_ids, edge_block_ids, ex_err, ex_id, id_to_block_names, id_to_edge_block_names, message(), num_edge_blk, and num_elem_blk.

◆ read_edge_blocks()

void libMesh::ExodusII_IO_Helper::read_edge_blocks ( MeshBase &  mesh)

Read in edge blocks, storing information in the BoundaryInfo object.

Definition at line 1655 of file exodusII_io_helper.C.

1656{
1657 LOG_SCOPE("read_edge_blocks()", "ExodusII_IO_Helper");
1658
1659 // Check for quick return if there are no edge blocks.
1660 if (num_edge_blk == 0)
1661 return;
1662
1663 // Build data structure that we can quickly search for edges
1664 // and then add required BoundaryInfo information. This is a
1665 // map from edge->key() to a list of (elem_id, edge_id) pairs
1666 // for the Edge in question. Since edge->key() is edge orientation
1667 // invariant, this map does not distinguish different orientations
1668 // of the same Edge. Since edge->key() is also not guaranteed to be
1669 // unique (though it is very unlikely for two distinct edges to have
1670 // the same key()), when we later look up an (elem_id, edge_id) pair
1671 // in the edge_map, we need to verify that the edge indeed matches
1672 // the searched edge by doing some further checks.
1673 typedef std::pair<dof_id_type, unsigned int> ElemEdgePair;
1674 std::unordered_map<dof_id_type, std::vector<ElemEdgePair>> edge_map;
1675 std::unique_ptr<Elem> edge_ptr;
1676 for (const auto & elem : mesh.element_ptr_range())
1677 for (auto e : elem->edge_index_range())
1678 {
1679 elem->build_edge_ptr(edge_ptr, e);
1680 dof_id_type edge_key = edge_ptr->key();
1681
1682 // Creates vector if not already there
1683 auto & vec = edge_map[edge_key];
1684 vec.emplace_back(elem->id(), e);
1685
1686 // If edge_ptr is a higher-order Elem (EDGE3 or higher) then also add
1687 // a map entry for the lower-order (EDGE2) element which has matching
1688 // vertices. This allows us to match lower-order edge blocks to edges
1689 // of higher-order 3D elems (e.g. HEX20, TET10) and simplifies the
1690 // definition of edge blocks.
1691 if (edge_ptr->default_order() != FIRST)
1692 {
1693 // Construct a temporary low-order edge so that we can compute its key()
1694 auto low_order_edge =
1696
1697 // Assign node pointers to low-order edge
1698 for (unsigned int v=0; v<edge_ptr->n_vertices(); ++v)
1699 low_order_edge->set_node(v, edge_ptr->node_ptr(v));
1700
1701 // Compute the key for the temporary low-order edge we just built
1702 dof_id_type low_order_edge_key = low_order_edge->key();
1703
1704 // Add this key to the map associated with the same (elem,
1705 // edge) pair as the higher-order edge
1706 auto & low_order_vec = edge_map[low_order_edge_key];
1707 low_order_vec.emplace_back(elem->id(), e);
1708 }
1709 }
1710
1711 // Get reference to the mesh's BoundaryInfo object, as we will be
1712 // adding edges to this below.
1714
1715 for (const auto & edge_block_id : edge_block_ids)
1716 {
1717 // exII::ex_get_block() output parameters. Unlike the other
1718 // "extended" APIs, exII::ex_get_block() does not use a
1719 // parameter struct.
1720 int num_edge_this_blk = 0;
1721 int num_nodes_per_edge = 0;
1722 int num_edges_per_edge = 0;
1723 int num_faces_per_edge = 0;
1724 int num_attr_per_edge = 0;
1725 ex_err = exII::ex_get_block(ex_id,
1726 exII::EX_EDGE_BLOCK,
1727 edge_block_id,
1728 elem_type.data(),
1729 &num_edge_this_blk,
1730 &num_nodes_per_edge,
1731 &num_edges_per_edge, // 0 or -1 for edge blocks
1732 &num_faces_per_edge, // 0 or -1 for edge blocks
1733 &num_attr_per_edge);
1734
1735 EX_CHECK_ERR(ex_err, "Error getting edge block info.");
1736 message("Info retrieved successfully for block: ", edge_block_id);
1737
1738 // Read in the connectivity of the edges of this block,
1739 // watching out for the case where we actually have no
1740 // elements in this block (possible with parallel files)
1741 connect.resize(num_nodes_per_edge * num_edge_this_blk);
1742
1743 if (!connect.empty())
1744 {
1745 ex_err = exII::ex_get_conn(ex_id,
1746 exII::EX_EDGE_BLOCK,
1747 edge_block_id,
1748 connect.data(), // node_conn
1749 nullptr, // elem_edge_conn (unused)
1750 nullptr); // elem_face_conn (unused)
1751
1752 EX_CHECK_ERR(ex_err, "Error reading block connectivity.");
1753 message("Connectivity retrieved successfully for block: ", edge_block_id);
1754
1755 // All edge types have an identity mapping from the corresponding
1756 // Exodus type, so we don't need to bother with mapping ids, but
1757 // we do need to know what kind of elements to build.
1758 const auto & conv = get_conversion(std::string(elem_type.data()));
1759
1760 // Loop over indices in connectivity array, build edge elements,
1761 // look them up in the edge_map.
1762 for (auto [i, sz] = std::make_tuple(0u, connect.size()); i<sz; i+=num_nodes_per_edge)
1763 {
1764 auto edge = Elem::build(conv.libmesh_elem_type());
1765 for (int n=0; n<num_nodes_per_edge; ++n)
1766 {
1767 auto exodus_node_id = this->connect[i+n];
1768 dof_id_type libmesh_node_id = this->get_libmesh_node_id(exodus_node_id);
1769 edge->set_node(n, mesh.node_ptr(libmesh_node_id));
1770 }
1771
1772 // Compute key for the edge Elem we just built.
1773 dof_id_type edge_key = edge->key();
1774
1775 // If this key is not found in the edge_map, which is
1776 // supposed to include every edge in the Mesh, then we
1777 // will throw an error now.
1778 auto & elem_edge_pair_vec =
1779 libmesh_map_find(edge_map, edge_key);
1780
1781 for (const auto & elem_edge_pair : elem_edge_pair_vec)
1782 {
1783 // We only want to match edges which have the same
1784 // nodes (possibly with different orientation) to the one in the
1785 // Exodus file, otherwise we ignore this elem_edge_pair.
1786 //
1787 // Note: this also handles the situation where two
1788 // edges have the same key (hash collision) as then
1789 // this check avoids a false positive.
1790
1791 // Build edge indicated by elem_edge_pair
1792 mesh.elem_ptr(elem_edge_pair.first)->
1793 build_edge_ptr(edge_ptr, elem_edge_pair.second);
1794
1795 // Determine whether this candidate edge is a "real" match,
1796 // i.e. has the same nodes with a possibly different
1797 // orientation. Note that here we only check that
1798 // the vertices match regardless of how many nodes
1799 // the edge has, which allows us to match a
1800 // lower-order edge to a higher-order Elem.
1801 bool is_match =
1802 ((edge_ptr->node_id(0) == edge->node_id(0)) && (edge_ptr->node_id(1) == edge->node_id(1))) ||
1803 ((edge_ptr->node_id(0) == edge->node_id(1)) && (edge_ptr->node_id(1) == edge->node_id(0)));
1804
1805 if (is_match)
1806 {
1807 // Add this (elem, edge, id) combo to the BoundaryInfo object.
1808 bi.add_edge(elem_edge_pair.first,
1809 elem_edge_pair.second,
1810 edge_block_id);
1811 }
1812 } // end loop over elem_edge_pairs
1813 } // end loop over connectivity array
1814
1815 // Set edgeset name in the BoundaryInfo object.
1816 bi.edgeset_name(edge_block_id) = id_to_edge_block_names[edge_block_id];
1817 } // end if !connect.empty()
1818 } // end for edge_block_id : edge_block_ids
1819}
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure.
std::string & edgeset_name(boundary_id_type id)
static ElemType first_order_equivalent_type(const ElemType et)
Definition elem.C:3201
dof_id_type get_libmesh_node_id(int exodus_node_id)
Helper function that takes a (1-based) Exodus node/elem id and determines the corresponding libMesh N...
virtual const Node * node_ptr(const dof_id_type i) const =0

References libMesh::BoundaryInfo::add_edge(), libMesh::Elem::build(), libMesh::Elem::build_edge_ptr(), connect, edge_block_ids, libMesh::Elem::edge_index_range(), libMesh::BoundaryInfo::edgeset_name(), libMesh::MeshBase::elem_ptr(), elem_type, ex_err, ex_id, libMesh::FIRST, libMesh::Elem::first_order_equivalent_type(), libMesh::MeshBase::get_boundary_info(), get_conversion(), get_libmesh_node_id(), libMesh::DofObject::id(), id_to_edge_block_names, mesh, message(), libMesh::MeshBase::node_ptr(), and num_edge_blk.

◆ read_elem_in_block()

void libMesh::ExodusII_IO_Helper::read_elem_in_block ( int  block)

Reads all of the element connectivity for block block in the ExodusII mesh file.

Definition at line 1410 of file exodusII_io_helper.C.

1411{
1412 LOG_SCOPE("read_elem_in_block()", "ExodusII_IO_Helper");
1413
1414 libmesh_assert_less (block, block_ids.size());
1415 elem_node_counts.clear();
1416 elem_face_counts.clear();
1417
1418 // Unlike the other "extended" APIs, this one does not use a parameter struct.
1419 int num_edges_per_elem = 0;
1420 int num_faces_per_elem = 0;
1421 int num_node_data_per_elem = 0;
1422 ex_err = exII::ex_get_block(ex_id,
1423 exII::EX_ELEM_BLOCK,
1424 block_ids[block],
1425 elem_type.data(),
1427 &num_node_data_per_elem,
1428 &num_edges_per_elem, // 0 or -1 if no "extended" block info
1429 &num_faces_per_elem, // 0 or -1 if no "extended" block info
1430 &num_attr);
1431
1432 EX_CHECK_ERR(ex_err, "Error getting block info.");
1433 message("Info retrieved successfully for block: ", block);
1434
1435 // Nemesis uses "Empty" as the element type for blocks with no
1436 // elements on the current processor. There is no element conversion
1437 // for that sentinel type, nor is one needed for an empty block.
1438 const bool is_bezier = is_bezier_elem(elem_type.data());
1439 const Conversion * conversion = nullptr;
1440 if (num_elem_this_blk || is_bezier)
1441 conversion = &get_conversion(std::string(elem_type.data()));
1442
1443 const bool is_c0polygon =
1444 conversion && conversion->libmesh_elem_type() == C0POLYGON;
1445 const bool is_c0polyhedron =
1446 conversion && conversion->libmesh_elem_type() == C0POLYHEDRON;
1447
1448 // Warn or error when we don't currently support reading blocks with extended info.
1449 // Note: the docs say -1 will be returned for this but I found that it was
1450 // actually 0, so not sure which it will be in general.
1451 if (is_c0polyhedron && !(num_edges_per_elem == 0) && !(num_edges_per_elem == -1))
1452 libmesh_error_msg("Error: Exodus NFACED element blocks with edge "
1453 "connectivity are not currently supported.");
1454 else if (!(num_edges_per_elem == 0) && !(num_edges_per_elem == -1))
1455 libmesh_warning("Exodus files with extended edge connectivity not currently supported.");
1456 if (!is_c0polyhedron && !(num_faces_per_elem == 0) && !(num_faces_per_elem == -1))
1457 libmesh_warning("Exodus files with extended face connectivity not currently supported.");
1458
1459 // If we have a Bezier element here, then we've packed constraint
1460 // vector connectivity at the end of the nodal connectivity, and
1461 // num_nodes_per_elem reflected both.
1462 if (is_bezier)
1463 {
1464 libmesh_assert(conversion);
1465 num_nodes_per_elem = conversion->n_nodes;
1466 }
1467 else if (is_c0polygon)
1468 {
1470
1471 if (!elem_node_counts.empty())
1472 {
1473 ex_err = exII::ex_get_entity_count_per_polyhedra
1474 (ex_id,
1475 exII::EX_ELEM_BLOCK,
1476 block_ids[block],
1477 elem_node_counts.data());
1478 EX_CHECK_ERR(ex_err, "Error reading polygon node counts");
1479 }
1480
1481 int counted_nodes = 0;
1482 for (const auto count : elem_node_counts)
1483 counted_nodes += count;
1484
1485 libmesh_error_msg_if(counted_nodes != num_node_data_per_elem,
1486 "Error: Exodus NSIDED block "
1487 << block_ids[block]
1488 << " says it has " << num_node_data_per_elem
1489 << " total node entries, but its per-element "
1490 << "node counts sum to " << counted_nodes << ".");
1491
1493 }
1494 else if (is_c0polyhedron)
1495 {
1496 if (c0polyhedron_face_connect.empty())
1497 this->read_face_blocks();
1498
1500
1501 if (!elem_face_counts.empty())
1502 {
1503 ex_err = exII::ex_get_entity_count_per_polyhedra
1504 (ex_id,
1505 exII::EX_ELEM_BLOCK,
1506 block_ids[block],
1507 elem_face_counts.data());
1508 EX_CHECK_ERR(ex_err, "Error reading polyhedron face counts");
1509 }
1510
1511 int counted_faces = 0;
1512 for (const auto count : elem_face_counts)
1513 counted_faces += count;
1514
1515 libmesh_error_msg_if(counted_faces != num_faces_per_elem,
1516 "Error: Exodus NFACED block "
1517 << block_ids[block]
1518 << " says it has " << num_faces_per_elem
1519 << " total face entries, but its per-element "
1520 << "face counts sum to " << counted_faces << ".");
1521
1523 }
1524 else
1525 num_nodes_per_elem = num_node_data_per_elem;
1526
1527 if (verbose)
1528 {
1529 libMesh::out << "Read a block of " << num_elem_this_blk
1530 << " " << elem_type.data() << "(s)";
1531 if (is_c0polygon)
1532 libMesh::out << " having " << num_node_data_per_elem
1533 << " total node entries.";
1534 else if (is_c0polyhedron)
1535 libMesh::out << " having " << num_faces_per_elem
1536 << " total face entries.";
1537 else
1538 libMesh::out << " having " << num_nodes_per_elem
1539 << " nodes per element.";
1540 libMesh::out << std::endl;
1541 }
1542
1543 // Read in the connectivity of the elements of this block,
1544 // watching out for the case where we actually have no
1545 // elements in this block (possible with parallel files)
1546 connect.resize(is_c0polygon ?
1547 num_node_data_per_elem :
1548 is_c0polyhedron ?
1549 num_faces_per_elem :
1550 num_node_data_per_elem*num_elem_this_blk);
1551
1552 if (!connect.empty())
1553 {
1554 ex_err = exII::ex_get_conn(ex_id,
1555 exII::EX_ELEM_BLOCK,
1556 block_ids[block],
1557 is_c0polyhedron ? nullptr : connect.data(),
1558 nullptr, // elem_edge_conn (unused)
1559 is_c0polyhedron ? connect.data() : nullptr);
1560
1561 EX_CHECK_ERR(ex_err, "Error reading block connectivity.");
1562 message("Connectivity retrieved successfully for block: ", block);
1563 }
1564
1565 // If we had any attributes for this block, check to see if some of
1566 // them were Bezier-extension attributes.
1567
1568 // num_attr above is zero, not actually the number of block attributes?
1569 // ex_get_attr_param *also* gives me zero? Really, Exodus?
1570#if EX_API_VERS_NODOT >= 800
1571 int real_n_attr = exII::ex_get_attribute_count(ex_id, exII::EX_ELEM_BLOCK, block_ids[block]);
1572 EX_CHECK_ERR(real_n_attr, "Error getting number of element block attributes.");
1573
1574 if (real_n_attr > 0)
1575 {
1576 std::vector<exII::ex_attribute> attributes(real_n_attr);
1577
1578 ex_err = exII::ex_get_attribute_param(ex_id, exII::EX_ELEM_BLOCK, block_ids[block], attributes.data());
1579 EX_CHECK_ERR(ex_err, "Error getting element block attribute parameters.");
1580
1581 ex_err = exII::ex_get_attributes(ex_id, real_n_attr, attributes.data());
1582 EX_CHECK_ERR(ex_err, "Error getting element block attribute values.");
1583
1584 for (auto attr : attributes)
1585 {
1586 if (std::string("bex_elem_degrees") == attr.name)
1587 {
1588 if (attr.type != exII::EX_INTEGER)
1589 libmesh_error_msg("Found non-integer bex_elem_degrees");
1590
1591 if (attr.value_count > 3)
1592 libmesh_error_msg("Looking for at most 3 bex_elem_degrees; found " << attr.value_count);
1593
1594 libmesh_assert(is_bezier);
1595
1596 std::vector<int> bex_elem_degrees(3); // max dim
1597
1598 const int * as_int = static_cast<int *>(attr.values);
1599 std::copy(as_int, as_int+attr.value_count, bex_elem_degrees.begin());
1600
1601
1602 // Right now Bezier extraction elements aren't possible
1603 // for p>2 and aren't useful for p<2, and we don't
1604 // support anisotropic p...
1605#ifndef NDEBUG
1606 libmesh_assert(conversion);
1607 for (auto d : IntRange<int>(0, conversion->dim))
1608 libmesh_assert_equal_to(bex_elem_degrees[d], 2);
1609#endif
1610 }
1611 // ex_get_attributes did a values=calloc(); free() is our job.
1612 if (attr.values)
1613 free(attr.values);
1614 }
1615 }
1616
1617 if (is_bezier)
1618 {
1619 // We'd better have the number of cvs we expect
1620 if( num_node_data_per_elem > num_nodes_per_elem )
1621 bex_num_elem_cvs = num_node_data_per_elem / 2;
1622 else
1624 libmesh_assert_greater_equal(bex_num_elem_cvs, 0);
1625
1626 // The old connect vector is currently a mix of the expected
1627 // connectivity and any Bezier extraction connectivity;
1628 // disentangle that, if necessary.
1630 if (num_node_data_per_elem > num_nodes_per_elem)
1631 {
1632 std::vector<int> old_connect(bex_num_elem_cvs * num_elem_this_blk);
1633 old_connect.swap(connect);
1634 auto src = old_connect.data();
1635 auto dst = connect.data();
1636 for (auto e : IntRange<std::size_t>(0, num_elem_this_blk))
1637 {
1638 std::copy(src, src + bex_num_elem_cvs, dst);
1639 src += bex_num_elem_cvs;
1640 dst += bex_num_elem_cvs;
1641
1642 bex_cv_conn[e].resize(bex_num_elem_cvs);
1643 std::copy(src, src + bex_num_elem_cvs,
1644 bex_cv_conn[e].begin());
1645 src += bex_num_elem_cvs;
1646 }
1647 }
1648 }
1649
1650#endif // EX_API_VERS_NODOT >= 800
1651}
unsigned int dim
void ErrorVector unsigned int
void read_face_blocks()
Reads NSIDED face blocks used by NFACED element blocks.
std::vector< std::vector< long unsigned int > > bex_cv_conn

References bex_cv_conn, bex_num_elem_cvs, block_ids, libMesh::C0POLYGON, libMesh::C0POLYHEDRON, c0polyhedron_face_connect, connect, libMesh::ExodusII_IO_Helper::Conversion::dim, elem_face_counts, elem_node_counts, elem_type, ex_err, ex_id, get_conversion(), libMesh::libmesh_assert(), libMesh::ExodusII_IO_Helper::Conversion::libmesh_elem_type(), message(), libMesh::ExodusII_IO_Helper::Conversion::n_nodes, num_attr, num_elem_this_blk, num_nodes_per_elem, libMesh::out, read_face_blocks(), and verbose.

◆ read_elem_num_map()

void libMesh::ExodusII_IO_Helper::read_elem_num_map ( )

Reads the optional node_num_map from the ExodusII mesh file.

Definition at line 1823 of file exodusII_io_helper.C.

1824{
1825 elem_num_map.resize(num_elem);
1826
1827 // Note: we cannot use the exII::ex_get_num_map() here because it
1828 // (apparently) does not behave like ex_get_elem_num_map() when
1829 // there is no elem number map in the file: it throws an error
1830 // instead of returning a default identity array (1,2,3,...).
1831 ex_err = exII::ex_get_elem_num_map
1832 (ex_id, elem_num_map.empty() ? nullptr : elem_num_map.data());
1833
1834 EX_CHECK_ERR(ex_err, "Error retrieving element number map.");
1835 message("Element numbering map retrieved successfully.");
1836
1837 if (num_elem)
1838 {
1839 // The elem_num_map may contain ids larger than num_elem. In
1840 // other words, the elem_num_map is not necessarily just a
1841 // permutation of the "trivial" 1,2,3,... mapping, it can
1842 // contain effectively "any" numbers. Therefore, to get
1843 // "_end_elem_id", we need to check what the max entry in the
1844 // elem_num_map is.
1845 auto it = std::max_element(elem_num_map.begin(), elem_num_map.end());
1846 _end_elem_id = *it;
1847 }
1848 else
1849 _end_elem_id = 0;
1850
1851 if (verbose)
1852 {
1853 libMesh::out << "[" << this->processor_id() << "] elem_num_map[i] = ";
1854 for (unsigned int i=0; i<static_cast<unsigned int>(std::min(10, num_elem-1)); ++i)
1855 libMesh::out << elem_num_map[i] << ", ";
1856 libMesh::out << "... " << elem_num_map.back() << std::endl;
1857 }
1858}

References _end_elem_id, elem_num_map, ex_err, ex_id, message(), num_elem, libMesh::out, libMesh::ParallelObject::processor_id(), and verbose.

◆ read_elemental_var_values()

void libMesh::ExodusII_IO_Helper::read_elemental_var_values ( std::string  elemental_var_name,
int  time_step,
std::map< dof_id_type, Real > &  elem_var_value_map 
)

Reads elemental values for the variable 'elemental_var_name' at the specified timestep into the 'elem_var_value_map' which is passed in.

Definition at line 2417 of file exodusII_io_helper.C.

2420{
2421 LOG_SCOPE("read_elemental_var_values()", "ExodusII_IO_Helper");
2422
2424
2425 // See if we can find the variable we are looking for
2426 unsigned int var_index = 0;
2427 bool found = false;
2428
2429 // Do a linear search for elem_var_name in elemental_var_names
2430 for (; var_index != elem_var_names.size(); ++var_index)
2431 if (elem_var_names[var_index] == elemental_var_name)
2432 {
2433 found = true;
2434 break;
2435 }
2436
2437 if (!found)
2438 {
2439 libMesh::err << "Available variables: " << std::endl;
2440 for (const auto & var_name : elem_var_names)
2441 libMesh::err << var_name << std::endl;
2442
2443 libmesh_error_msg("Unable to locate variable named: " << elemental_var_name);
2444 }
2445
2446 // Sequential index which we can use to look up the element ID in the elem_num_map.
2447 unsigned ex_el_num = 0;
2448
2449 // Element variable truth table
2450 std::vector<int> var_table(block_ids.size() * elem_var_names.size());
2451 exII::ex_get_truth_table(ex_id, exII::EX_ELEM_BLOCK, block_ids.size(), elem_var_names.size(), var_table.data());
2452
2453 for (unsigned i=0; i<static_cast<unsigned>(num_elem_blk); i++)
2454 {
2455 ex_err = exII::ex_get_block(ex_id,
2456 exII::EX_ELEM_BLOCK,
2457 block_ids[i],
2458 /*elem_type=*/nullptr,
2460 /*num_nodes_per_entry=*/nullptr,
2461 /*num_edges_per_entry=*/nullptr,
2462 /*num_faces_per_entry=*/nullptr,
2463 /*num_attr=*/nullptr);
2464 EX_CHECK_ERR(ex_err, "Error getting number of elements in block.");
2465
2466 // If the current variable isn't active on this subdomain, advance
2467 // the index by the number of elements on this block and go to the
2468 // next loop iteration.
2469 if (!var_table[elem_var_names.size()*i + var_index])
2470 {
2471 ex_el_num += num_elem_this_blk;
2472 continue;
2473 }
2474
2475 std::vector<Real> block_elem_var_values(num_elem_this_blk);
2476
2477 ex_err = exII::ex_get_var
2478 (ex_id,
2479 time_step,
2480 exII::EX_ELEM_BLOCK,
2481 var_index+1,
2482 block_ids[i],
2484 MappedInputVector(block_elem_var_values, _single_precision).data());
2485 EX_CHECK_ERR(ex_err, "Error getting elemental values.");
2486
2487 for (unsigned j=0; j<static_cast<unsigned>(num_elem_this_blk); j++)
2488 {
2489 // Determine the libmesh id of the element with zero-based
2490 // index "ex_el_num". This function expects a one-based
2491 // index, so we add 1 to ex_el_num when we pass it in.
2492 auto libmesh_elem_id =
2493 this->get_libmesh_elem_id(ex_el_num + 1);
2494
2495 // Store the elemental value in the map.
2496 elem_var_value_map[libmesh_elem_id] = block_elem_var_values[j];
2497
2498 // Go to the next sequential element ID.
2499 ex_el_num++;
2500 }
2501 }
2502}
dof_id_type get_libmesh_elem_id(int exodus_elem_id)

References _single_precision, block_ids, elem_var_names, ELEMENTAL, libMesh::err, ex_err, ex_id, get_libmesh_elem_id(), num_elem_blk, num_elem_this_blk, and read_var_names().

◆ read_elemset()

void libMesh::ExodusII_IO_Helper::read_elemset ( int  id,
int  offset 
)

Reads information about elemset id and inserts it into the global elemset array at the position offset.

Definition at line 2013 of file exodusII_io_helper.C.

2014{
2015 LOG_SCOPE("read_elemset()", "ExodusII_IO_Helper");
2016
2017 libmesh_assert_less (id, elemset_ids.size());
2018 libmesh_assert_less (id, num_elems_per_set.size());
2019 libmesh_assert_less (id, num_elem_df_per_set.size());
2020 libmesh_assert_less_equal (offset, elemset_list.size());
2021
2022 ex_err = exII::ex_get_set_param(ex_id,
2023 exII::EX_ELEM_SET,
2024 elemset_ids[id],
2025 &num_elems_per_set[id],
2026 &num_elem_df_per_set[id]);
2027 EX_CHECK_ERR(ex_err, "Error retrieving elemset parameters.");
2028 message("Parameters retrieved successfully for elemset: ", id);
2029
2030
2031 // It's OK for offset==elemset_list.size() as long as num_elems_per_set[id]==0
2032 // because in that case we don't actually read anything...
2033 #ifdef DEBUG
2034 if (static_cast<unsigned int>(offset) == elemset_list.size())
2035 libmesh_assert_equal_to (num_elems_per_set[id], 0);
2036 #endif
2037
2038 // Don't call ex_get_set() unless there are actually elems there to get.
2039 // Exodus prints an annoying warning in DEBUG mode otherwise...
2040 if (num_elems_per_set[id] > 0)
2041 {
2042 ex_err = exII::ex_get_set(ex_id,
2043 exII::EX_ELEM_SET,
2044 elemset_ids[id],
2045 &elemset_list[offset],
2046 /*set_extra_list=*/nullptr);
2047 EX_CHECK_ERR(ex_err, "Error retrieving elemset data.");
2048 message("Data retrieved successfully for elemset: ", id);
2049
2050 // Create vector containing elemset ids for each element in the set
2051 for (int i=0; i<num_elems_per_set[id]; i++)
2052 elemset_id_list[i+offset] = elemset_ids[id];
2053 }
2054}
std::vector< int > num_elem_df_per_set

References elemset_id_list, elemset_ids, elemset_list, ex_err, ex_id, message(), num_elem_df_per_set, and num_elems_per_set.

Referenced by write_elemset_data().

◆ read_elemset_data()

void libMesh::ExodusII_IO_Helper::read_elemset_data ( int  timestep,
std::vector< std::string > &  var_names,
std::vector< std::set< elemset_id_type > > &  elemset_ids_in,
std::vector< std::map< std::pair< dof_id_type, elemset_id_type >, Real > > &  elemset_vals 
)

Read elemset variables, if any, into the provided data structures.

Definition at line 4828 of file exodusII_io_helper.C.

4833{
4834 LOG_SCOPE("read_elemset_data()", "ExodusII_IO_Helper");
4835
4836 // This reads the elemset variable names into the local
4837 // elemset_var_names data structure.
4838 this->read_var_names(ELEMSET);
4839
4840 // Debugging
4841 // libMesh::out << "elmeset variable names:" << std::endl;
4842 // for (const auto & name : elemset_var_names)
4843 // libMesh::out << name << " ";
4844 // libMesh::out << std::endl;
4845
4846 if (num_elemset_vars)
4847 {
4848 // Debugging
4849 // std::cout << "Reading " << num_elem_sets
4850 // << " elemsets and " << num_elemset_vars
4851 // << " elemset variables." << std::endl;
4852
4853 // Read the elemset data truth table.
4854 std::vector<int> elemset_var_tab(num_elem_sets * num_elemset_vars);
4855 exII::ex_get_truth_table(ex_id,
4856 exII::EX_ELEM_SET, // exII::ex_entity_type
4859 elemset_var_tab.data());
4860 EX_CHECK_ERR(ex_err, "Error reading elemset variable truth table.");
4861
4862 // Debugging
4863 // libMesh::out << "Elemset variable truth table:" << std::endl;
4864 // for (const auto & val : elemset_var_tab)
4865 // libMesh::out << val << " ";
4866 // libMesh::out << std::endl;
4867
4868 // Debugging
4869 // for (auto i : make_range(num_elem_sets))
4870 // {
4871 // for (auto j : make_range(num_elemset_vars))
4872 // libMesh::out << elemset_var_tab[num_elemset_vars*i + j] << " ";
4873 // libMesh::out << std::endl;
4874 // }
4875
4876 // Set up/allocate space in incoming data structures. All vectors are
4877 // num_elemset_vars in length.
4878 var_names = elemset_var_names;
4879 elemset_ids_in.resize(num_elemset_vars);
4880 elemset_vals.resize(num_elemset_vars);
4881
4882 // Read the elemset data
4883 int offset=0;
4884 for (int es=0; es<num_elem_sets; ++es)
4885 {
4886 offset += (es > 0 ? num_elems_per_set[es-1] : 0);
4887 for (int var=0; var<num_elemset_vars; ++var)
4888 {
4889 int is_present = elemset_var_tab[num_elemset_vars*es + var];
4890
4891 if (is_present)
4892 {
4893 // Debugging
4894 // libMesh::out << "Variable " << var << " is present on elemset " << es << std::endl;
4895
4896 // Record the fact that this variable is defined on this elemset.
4897 elemset_ids_in[var].insert(elemset_ids[es]);
4898
4899 // Note: the assumption here is that a previous call
4900 // to this->read_elemset_info() has already set the
4901 // values of num_elems_per_set, so we just use those values here.
4902 std::vector<Real> elemset_var_vals(num_elems_per_set[es]);
4903 ex_err = exII::ex_get_var
4904 (ex_id,
4905 timestep,
4906 exII::EX_ELEM_SET, // exII::ex_entity_type
4907 var + 1, // 1-based sideset variable index!
4908 elemset_ids[es],
4910 MappedInputVector(elemset_var_vals, _single_precision).data());
4911 EX_CHECK_ERR(ex_err, "Error reading elemset variable.");
4912
4913 for (int i=0; i<num_elems_per_set[es]; ++i)
4914 {
4915 dof_id_type exodus_elem_id = elemset_list[i + offset];
4916
4917 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4918 // but it apparently is never set up, so just
4919 // subtract 1 from the Exodus elem id.
4920 dof_id_type converted_elem_id = exodus_elem_id - 1;
4921
4922 // Make key based on the elem and set ids
4923 auto key = std::make_pair(converted_elem_id,
4924 static_cast<elemset_id_type>(elemset_ids[es]));
4925
4926 // Store value in the map
4927 elemset_vals[var].emplace(key, elemset_var_vals[i]);
4928 } // end for (i)
4929 } // end if (present)
4930 } // end for (var)
4931 } // end for (es)
4932 } // end if (num_elemset_vars)
4933}
std::vector< std::string > elemset_var_names

References _single_precision, ELEMSET, elemset_ids, elemset_list, elemset_var_names, ex_err, ex_id, num_elem_sets, num_elems_per_set, num_elemset_vars, and read_var_names().

◆ read_elemset_info()

void libMesh::ExodusII_IO_Helper::read_elemset_info ( )

Reads information about all of the elemsets in the ExodusII mesh file.

Definition at line 1926 of file exodusII_io_helper.C.

1927{
1928 elemset_ids.resize(num_elem_sets);
1929 if (num_elem_sets > 0)
1930 {
1931 ex_err = exII::ex_get_ids(ex_id,
1932 exII::EX_ELEM_SET,
1933 elemset_ids.data());
1934 EX_CHECK_ERR(ex_err, "Error retrieving elemset information.");
1935 message("All elemset information retrieved successfully.");
1936
1937 // Resize appropriate data structures -- only do this once outside the loop
1940
1941 // Inquire about the length of the concatenated elemset list
1943 inquire(*this, exII::EX_INQ_ELS_LEN,
1944 "Error retrieving length of the concatenated elem sets element list!");
1945
1948
1949 // Debugging
1950 // libMesh::out << "num_elem_all_elemsets = " << num_elem_all_elemsets << std::endl;
1951 }
1952
1953 char name_buffer[libmesh_max_str_length+1];
1954 for (int i=0; i<num_elem_sets; ++i)
1955 {
1956 ex_err = exII::ex_get_name(ex_id, exII::EX_ELEM_SET,
1957 elemset_ids[i], name_buffer);
1958 EX_CHECK_ERR(ex_err, "Error getting node set name.");
1959 id_to_elemset_names[elemset_ids[i]] = name_buffer;
1960 }
1961 message("All elem set names retrieved successfully.");
1962}
std::map< int, std::string > id_to_elemset_names

References elemset_id_list, elemset_ids, elemset_list, ex_err, ex_id, id_to_elemset_names, message(), num_elem_all_elemsets, num_elem_df_per_set, num_elem_sets, and num_elems_per_set.

Referenced by write_elemset_data().

◆ read_face_blocks()

void libMesh::ExodusII_IO_Helper::read_face_blocks ( )

Reads NSIDED face blocks used by NFACED element blocks.

Definition at line 1290 of file exodusII_io_helper.C.

1291{
1292 LOG_SCOPE("read_face_blocks()", "ExodusII_IO_Helper");
1293
1294 if (!c0polyhedron_face_connect.empty())
1295 return;
1296
1297 libmesh_error_msg_if(num_face_blk == 0,
1298 "Error: Exodus NFACED element block found, "
1299 "but the file has no face blocks.");
1300
1301 std::vector<int> face_block_ids(num_face_blk);
1302 ex_err = exII::ex_get_ids(ex_id,
1303 exII::EX_FACE_BLOCK,
1304 face_block_ids.data());
1305 EX_CHECK_ERR(ex_err, "Error getting face block IDs.");
1306
1309
1310 for (auto block : index_range(face_block_ids))
1311 {
1312 std::vector<char> face_type(libmesh_max_str_length+1);
1313 int num_face_this_blk = 0;
1314 int num_node_data_this_blk = 0;
1315 int num_edges_per_face = 0;
1316 int num_faces_per_face = 0;
1317 int num_attr_face = 0;
1318
1319 ex_err = exII::ex_get_block(ex_id,
1320 exII::EX_FACE_BLOCK,
1321 face_block_ids[block],
1322 face_type.data(),
1323 &num_face_this_blk,
1324 &num_node_data_this_blk,
1325 &num_edges_per_face,
1326 &num_faces_per_face,
1327 &num_attr_face);
1328 EX_CHECK_ERR(ex_err, "Error getting face block info.");
1329
1330 const auto & conv = get_conversion(std::string(face_type.data()));
1331 libmesh_error_msg_if(conv.libmesh_elem_type() != C0POLYGON,
1332 "Error: NFACED polyhedron input currently expects "
1333 "NSIDED face blocks, but face block "
1334 << face_block_ids[block] << " has Exodus type "
1335 << face_type.data() << ".");
1336
1337 libmesh_error_msg_if
1338 (!(num_edges_per_face == 0) && !(num_edges_per_face == -1),
1339 "Error: Exodus NSIDED face block "
1340 << face_block_ids[block]
1341 << " has edge connectivity, which NFACED polyhedron input "
1342 << "does not currently support.");
1343 libmesh_error_msg_if
1344 (!(num_faces_per_face == 0) && !(num_faces_per_face == -1),
1345 "Error: Exodus NSIDED face block "
1346 << face_block_ids[block]
1347 << " has face-in-face connectivity, which NFACED polyhedron "
1348 << "input does not currently support.");
1349
1350 std::vector<int> face_node_counts(num_face_this_blk);
1351 if (!face_node_counts.empty())
1352 {
1353 ex_err = exII::ex_get_entity_count_per_polyhedra
1354 (ex_id,
1355 exII::EX_FACE_BLOCK,
1356 face_block_ids[block],
1357 face_node_counts.data());
1358 EX_CHECK_ERR(ex_err, "Error reading polyhedron face node counts");
1359 }
1360
1361 int counted_nodes = 0;
1362 for (const auto count : face_node_counts)
1363 counted_nodes += count;
1364
1365 libmesh_error_msg_if(counted_nodes != num_node_data_this_blk,
1366 "Error: Exodus NSIDED face block "
1367 << face_block_ids[block]
1368 << " says it has " << num_node_data_this_blk
1369 << " total node entries, but its per-face "
1370 << "node counts sum to " << counted_nodes << ".");
1371
1372 std::vector<int> face_connect(num_node_data_this_blk);
1373 if (!face_connect.empty())
1374 {
1375 ex_err = exII::ex_get_conn(ex_id,
1376 exII::EX_FACE_BLOCK,
1377 face_block_ids[block],
1378 face_connect.data(),
1379 nullptr,
1380 nullptr);
1381 EX_CHECK_ERR(ex_err, "Error reading polyhedron face connectivity.");
1382 }
1383
1384 std::size_t offset = 0;
1385 for (const auto count : face_node_counts)
1386 {
1387 libmesh_error_msg_if(count < 3,
1388 "Error: Exodus NSIDED face block "
1389 << face_block_ids[block]
1390 << " has a face with only "
1391 << count << " nodes.");
1392
1393 c0polyhedron_face_connect.emplace_back
1394 (face_connect.begin() + offset,
1395 face_connect.begin() + offset + count);
1396 offset += count;
1397 }
1398 }
1399
1400 libmesh_error_msg_if(c0polyhedron_face_connect.size() !=
1401 cast_int<std::size_t>(num_face),
1402 "Error: Exodus file says it has "
1403 << num_face << " faces, but its face blocks contain "
1404 << c0polyhedron_face_connect.size() << " faces.");
1405}

References libMesh::C0POLYGON, c0polyhedron_face_connect, ex_err, ex_id, get_conversion(), libMesh::index_range(), num_face, and num_face_blk.

Referenced by read_elem_in_block().

◆ read_global_values()

void libMesh::ExodusII_IO_Helper::read_global_values ( std::vector< Real > &  values,
int  timestep 
)

Reads the vector of global variables.

Definition at line 5445 of file exodusII_io_helper.C.

5446{
5447 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5448 return;
5449
5450 values.clear();
5451 values.resize(num_global_vars);
5452 ex_err = exII::ex_get_var
5453 (ex_id,
5454 timestep,
5455 exII::EX_GLOBAL,
5456 1, // var_index
5457 1, // obj_id
5459 MappedInputVector(values, _single_precision).data());
5460
5461 EX_CHECK_ERR(ex_err, "Error reading global values.");
5462}

References _run_only_on_proc0, _single_precision, ex_err, ex_id, num_global_vars, and libMesh::ParallelObject::processor_id().

◆ read_header()

ExodusHeaderInfo libMesh::ExodusII_IO_Helper::read_header ( ) const

Reads an ExodusII mesh file header, leaving this object's internal data structures unchanged.

Definition at line 850 of file exodusII_io_helper.C.

851{
852 // Read init params using newer API that reads into a struct. For
853 // backwards compatibility, assign local member values from struct
854 // afterwards. Note: using the new API allows us to automatically
855 // read edge and face block/set information if it's present in the
856 // file.
857 exII::ex_init_params params = {};
858 int err_flag = exII::ex_get_init_ext(ex_id, &params);
859 EX_CHECK_ERR(err_flag, "Error retrieving header info.");
860
861 // Extract required data into our struct
863 h.title.assign(params.title, params.title + MAX_LINE_LENGTH);
864 h.num_dim = params.num_dim;
865 h.num_nodes = params.num_nodes;
866 h.num_elem = params.num_elem;
867 h.num_elem_blk = params.num_elem_blk;
868 h.num_node_sets = params.num_node_sets;
869 h.num_side_sets = params.num_side_sets;
870 h.num_elem_sets = params.num_elem_sets;
871 h.num_edge_blk = params.num_edge_blk;
872 h.num_edge = params.num_edge;
873 h.num_face_blk = params.num_face_blk;
874 h.num_face = params.num_face;
875
876 // And return it
877 return h;
878}
This class is used as both an external data structure for passing around Exodus file header informati...

References ex_id, libMesh::ExodusHeaderInfo::num_dim, libMesh::ExodusHeaderInfo::num_edge, libMesh::ExodusHeaderInfo::num_edge_blk, libMesh::ExodusHeaderInfo::num_elem, libMesh::ExodusHeaderInfo::num_elem_blk, libMesh::ExodusHeaderInfo::num_elem_sets, libMesh::ExodusHeaderInfo::num_face, libMesh::ExodusHeaderInfo::num_face_blk, libMesh::ExodusHeaderInfo::num_node_sets, libMesh::ExodusHeaderInfo::num_nodes, libMesh::ExodusHeaderInfo::num_side_sets, and libMesh::ExodusHeaderInfo::title.

Referenced by read_and_store_header_info().

◆ read_nodal_var_values()

void libMesh::ExodusII_IO_Helper::read_nodal_var_values ( std::string  nodal_var_name,
int  time_step 
)

Reads the nodal values for the variable 'nodal_var_name' at the specified time into the 'nodal_var_values' array.

Definition at line 2192 of file exodusII_io_helper.C.

2193{
2194 LOG_SCOPE("read_nodal_var_values()", "ExodusII_IO_Helper");
2195
2196 // Read the nodal variable names from file, so we can see if we have the one we're looking for
2197 this->read_var_names(NODAL);
2198
2199 // See if we can find the variable we are looking for
2200 unsigned int var_index = 0;
2201 bool found = false;
2202
2203 // Do a linear search for nodal_var_name in nodal_var_names
2204 for (; var_index<nodal_var_names.size(); ++var_index)
2205 {
2206 found = (nodal_var_names[var_index] == nodal_var_name);
2207 if (found)
2208 break;
2209 }
2210
2211 if (!found)
2212 {
2213 libMesh::err << "Available variables: " << std::endl;
2214 for (const auto & var_name : nodal_var_names)
2215 libMesh::err << var_name << std::endl;
2216
2217 libmesh_error_msg("Unable to locate variable named: " << nodal_var_name);
2218 }
2219
2220 // Clear out any previously read nodal variable values
2221 this->nodal_var_values.clear();
2222
2223 std::vector<Real> unmapped_nodal_var_values(num_nodes);
2224
2225 // Call the Exodus API to read the nodal variable values
2226 ex_err = exII::ex_get_var
2227 (ex_id,
2228 time_step,
2229 exII::EX_NODAL,
2230 var_index+1,
2231 1, // exII::ex_entity_id, not sure exactly what this is but in the ex_get_nodal_var.c shim, they pass 1
2232 num_nodes,
2233 MappedInputVector(unmapped_nodal_var_values, _single_precision).data());
2234 EX_CHECK_ERR(ex_err, "Error reading nodal variable values!");
2235
2236 for (auto i : make_range(num_nodes))
2237 {
2238 // Determine the libmesh node id implied by "i". The
2239 // get_libmesh_node_id() helper function expects a 1-based
2240 // Exodus node id, so we construct the "implied" Exodus node id
2241 // from "i" by adding 1.
2242 //
2243 // If the user has set the "set_unique_ids_from_maps" flag to
2244 // true, then calling get_libmesh_node_id(i+1) will just return
2245 // i, otherwise it will determine the value (with error
2246 // checking) using this->node_num_map.
2247 auto libmesh_node_id = this->get_libmesh_node_id(/*exodus_node_id=*/i+1);
2248
2249 // Store the nodal value in the map.
2250 this->nodal_var_values[libmesh_node_id] = unmapped_nodal_var_values[i];
2251 }
2252}
std::map< dof_id_type, Real > nodal_var_values

References _single_precision, libMesh::err, ex_err, ex_id, get_libmesh_node_id(), libMesh::make_range(), NODAL, nodal_var_names, nodal_var_values, num_nodes, and read_var_names().

◆ read_node_num_map()

void libMesh::ExodusII_IO_Helper::read_node_num_map ( )

Reads the optional node_num_map from the ExodusII mesh file.

Definition at line 1043 of file exodusII_io_helper.C.

1044{
1045 node_num_map.resize(num_nodes);
1046
1047 // Note: we cannot use the exII::ex_get_num_map() here because it
1048 // (apparently) does not behave like ex_get_node_num_map() when
1049 // there is no node number map in the file: it throws an error
1050 // instead of returning a default identity array (1,2,3,...).
1051 ex_err = exII::ex_get_node_num_map
1052 (ex_id, node_num_map.empty() ? nullptr : node_num_map.data());
1053
1054 EX_CHECK_ERR(ex_err, "Error retrieving nodal number map.");
1055 message("Nodal numbering map retrieved successfully.");
1056
1057 if (verbose)
1058 {
1059 libMesh::out << "[" << this->processor_id() << "] node_num_map[i] = ";
1060 for (unsigned int i=0; i<static_cast<unsigned int>(std::min(10, num_nodes-1)); ++i)
1061 libMesh::out << node_num_map[i] << ", ";
1062 libMesh::out << "... " << node_num_map.back() << std::endl;
1063 }
1064}

References ex_err, ex_id, message(), node_num_map, num_nodes, libMesh::out, libMesh::ParallelObject::processor_id(), and verbose.

◆ read_nodes()

void libMesh::ExodusII_IO_Helper::read_nodes ( )

Reads the nodal data (x,y,z coordinates) from the ExodusII mesh file.

Definition at line 992 of file exodusII_io_helper.C.

993{
994 LOG_SCOPE("read_nodes()", "ExodusII_IO_Helper");
995
996 x.resize(num_nodes);
997 y.resize(num_nodes);
998 z.resize(num_nodes);
999
1000 if (num_nodes)
1001 {
1002 ex_err = exII::ex_get_coord
1003 (ex_id,
1004 MappedInputVector(x, _single_precision).data(),
1005 MappedInputVector(y, _single_precision).data(),
1006 MappedInputVector(z, _single_precision).data());
1007
1008 EX_CHECK_ERR(ex_err, "Error retrieving nodal data.");
1009 message("Nodal data retrieved successfully.");
1010 }
1011
1012 // If a nodal attribute bex_weight exists, we get spline weights
1013 // from it
1014 int n_nodal_attr = 0;
1015 ex_err = exII::ex_get_attr_param(ex_id, exII::EX_NODAL, 0, & n_nodal_attr);
1016 EX_CHECK_ERR(ex_err, "Error getting number of nodal attributes.");
1017
1018 if (n_nodal_attr > 0)
1019 {
1020 std::vector<std::vector<char>> attr_name_data
1021 (n_nodal_attr, std::vector<char>(libmesh_max_str_length + 1));
1022 std::vector<char *> attr_names(n_nodal_attr);
1023 for (auto i : index_range(attr_names))
1024 attr_names[i] = attr_name_data[i].data();
1025
1026 ex_err = exII::ex_get_attr_names(ex_id, exII::EX_NODAL, 0, attr_names.data());
1027 EX_CHECK_ERR(ex_err, "Error getting nodal attribute names.");
1028
1029 for (auto i : index_range(attr_names))
1030 if (std::string("bex_weight") == attr_names[i])
1031 {
1032 w.resize(num_nodes);
1033 ex_err =
1034 exII::ex_get_one_attr (ex_id, exII::EX_NODAL, 0, i+1,
1035 MappedInputVector(w, _single_precision).data());
1036 EX_CHECK_ERR(ex_err, "Error getting Bezier Extraction nodal weights");
1037 }
1038 }
1039}

References _single_precision, ex_err, ex_id, libMesh::index_range(), message(), num_nodes, w, x, y, and z.

◆ read_nodeset_data()

void libMesh::ExodusII_IO_Helper::read_nodeset_data ( int  timestep,
std::vector< std::string > &  var_names,
std::vector< std::set< boundary_id_type > > &  node_boundary_ids,
std::vector< std::map< BoundaryInfo::NodeBCTuple, Real > > &  bc_vals 
)

Read nodeset variables, if any, into the provided data structures.

Definition at line 4980 of file exodusII_io_helper.C.

4985{
4986 LOG_SCOPE("read_nodeset_data()", "ExodusII_IO_Helper");
4987
4988 // This reads the sideset variable names into the local
4989 // sideset_var_names data structure.
4990 this->read_var_names(NODESET);
4991
4992 if (num_nodeset_vars)
4993 {
4994 // Read the nodeset data truth table
4995 std::vector<int> nset_var_tab(num_node_sets * num_nodeset_vars);
4996 ex_err = exII::ex_get_truth_table
4997 (ex_id,
4998 exII::EX_NODE_SET,
5001 nset_var_tab.data());
5002 EX_CHECK_ERR(ex_err, "Error reading nodeset variable truth table.");
5003
5004 // Set up/allocate space in incoming data structures.
5005 var_names = nodeset_var_names;
5006 node_boundary_ids.resize(num_nodeset_vars);
5007 bc_vals.resize(num_nodeset_vars);
5008
5009 // Read the nodeset data.
5010 //
5011 // Note: we assume that the functions
5012 // 1.) this->read_nodeset_info() and
5013 // 2.) this->read_all_nodesets()
5014 // have already been called, so that we already know e.g. how
5015 // many nodes are in each set, their ids, etc.
5016 //
5017 // TODO: As a future optimization, we could read only the values
5018 // requested by the user by looking at the input parameter
5019 // var_names and checking whether it already has entries in
5020 // it.
5021 int offset=0;
5022 for (int ns=0; ns<num_node_sets; ++ns)
5023 {
5024 offset += (ns > 0 ? num_nodes_per_set[ns-1] : 0);
5025 for (int var=0; var<num_nodeset_vars; ++var)
5026 {
5027 int is_present = nset_var_tab[num_nodeset_vars*ns + var];
5028
5029 if (is_present)
5030 {
5031 // Record the fact that this variable is defined on this nodeset.
5032 node_boundary_ids[var].insert(nodeset_ids[ns]);
5033
5034 // Note: the assumption here is that a previous call
5035 // to this->read_nodeset_info() has already set the
5036 // values of num_nodes_per_set, so we just use those values here.
5037 std::vector<Real> nset_var_vals(num_nodes_per_set[ns]);
5038 ex_err = exII::ex_get_var
5039 (ex_id,
5040 timestep,
5041 exII::EX_NODE_SET,
5042 var + 1, // 1-based nodeset variable index!
5043 nodeset_ids[ns],
5045 MappedInputVector(nset_var_vals, _single_precision).data());
5046 EX_CHECK_ERR(ex_err, "Error reading nodeset variable.");
5047
5048 for (int i=0; i<num_nodes_per_set[ns]; ++i)
5049 {
5050 // The read_all_nodesets() function now reads all the node ids into the
5051 // node_sets_node_list vector, which is of length "total_nodes_in_all_sets"
5052 // The old read_nodset() function is no longer called as far as I can tell,
5053 // and should probably be removed? The "offset" that we are using only
5054 // depends on the current nodeset index and the num_nodes_per_set vector,
5055 // which gets filled in by the call to read_all_nodesets().
5056 dof_id_type exodus_node_id = node_sets_node_list[i + offset];
5057
5058 // FIXME: We should use exodus_node_num_to_libmesh for this,
5059 // but it apparently is never set up, so just
5060 // subtract 1 from the Exodus node id.
5061 dof_id_type converted_node_id = exodus_node_id - 1;
5062
5063 // Make a NodeBCTuple key from the converted information.
5064 BoundaryInfo::NodeBCTuple key = std::make_tuple
5065 (converted_node_id, nodeset_ids[ns]);
5066
5067 // Store (node, b_id) tuples in bc_vals[var]
5068 bc_vals[var].emplace(key, nset_var_vals[i]);
5069 } // end for (i)
5070 } // end if (present)
5071 } // end for (var)
5072 } // end for (ns)
5073 } // end if (num_nodeset_vars)
5074}
std::vector< std::string > nodeset_var_names

References _single_precision, ex_err, ex_id, node_sets_node_list, NODESET, nodeset_ids, nodeset_var_names, num_node_sets, num_nodes_per_set, num_nodeset_vars, and read_var_names().

◆ read_nodeset_info()

void libMesh::ExodusII_IO_Helper::read_nodeset_info ( )

Reads information about all of the nodesets in the ExodusII mesh file.

Definition at line 1897 of file exodusII_io_helper.C.

1898{
1899 nodeset_ids.resize(num_node_sets);
1900 if (num_node_sets > 0)
1901 {
1902 ex_err = exII::ex_get_ids(ex_id,
1903 exII::EX_NODE_SET,
1904 nodeset_ids.data());
1905 EX_CHECK_ERR(ex_err, "Error retrieving nodeset information.");
1906 message("All nodeset information retrieved successfully.");
1907
1908 // Resize appropriate data structures -- only do this once outside the loop
1911 }
1912
1913 char name_buffer[libmesh_max_str_length+1];
1914 for (int i=0; i<num_node_sets; ++i)
1915 {
1916 ex_err = exII::ex_get_name(ex_id, exII::EX_NODE_SET,
1917 nodeset_ids[i], name_buffer);
1918 EX_CHECK_ERR(ex_err, "Error getting node set name.");
1919 id_to_ns_names[nodeset_ids[i]] = name_buffer;
1920 }
1921 message("All node set names retrieved successfully.");
1922}

References ex_err, ex_id, id_to_ns_names, message(), nodeset_ids, num_node_df_per_set, num_node_sets, and num_nodes_per_set.

◆ read_num_time_steps()

void libMesh::ExodusII_IO_Helper::read_num_time_steps ( )

Reads the number of timesteps currently stored in the Exodus file and stores it in the num_time_steps variable.

Definition at line 2184 of file exodusII_io_helper.C.

2185{
2187 inquire(*this, exII::EX_INQ_TIME, "Error retrieving number of time steps");
2188}

References num_time_steps.

Referenced by read_and_store_header_info(), and read_time_steps().

◆ read_qa_records()

void libMesh::ExodusII_IO_Helper::read_qa_records ( )

Reads the QA records from an ExodusII file.

We can use this to detect when e.g. CUBIT 14+ was used to generate a Mesh file, and work around certain known bugs in that version.

Definition at line 916 of file exodusII_io_helper.C.

917{
918 // The QA records are four MAX_STR_LENGTH-byte character strings.
919 int num_qa_rec =
920 inquire(*this, exII::EX_INQ_QA, "Error retrieving number of QA records");
921
922 if (verbose)
923 libMesh::out << "Found "
924 << num_qa_rec
925 << " QA record(s) in the Exodus file."
926 << std::endl;
927
928 if (num_qa_rec > 0)
929 {
930 // Actual (num_qa_rec x 4) storage for strings. The object we
931 // pass to the Exodus API will just contain pointers into the
932 // qa_storage object, which will have all automatic memory
933 // management.
934 std::vector<std::vector<std::vector<char>>> qa_storage(num_qa_rec);
935 for (auto i : make_range(num_qa_rec))
936 {
937 qa_storage[i].resize(4);
938 for (auto j : make_range(4))
939 qa_storage[i][j].resize(libmesh_max_str_length+1);
940 }
941
942 // inner_array_t is a fixed-size array of 4 strings
943 typedef char * inner_array_t[4];
944
945 // There is at least one compiler (Clang 12.0.1) that complains about
946 // "a non-scalar type used in a pseudo-destructor expression" when
947 // we try to instantiate a std::vector of inner_array_t objects as in:
948 // std::vector<inner_array_t> qa_record(num_qa_rec);
949 // So, we instead attempt to achieve the same effect with a std::unique_ptr.
950 auto qa_record = std::make_unique<inner_array_t[]>(num_qa_rec);
951
952 // Create data structure to be passed to Exodus API by setting
953 // pointers to the actual strings which are in qa_storage.
954 for (auto i : make_range(num_qa_rec))
955 for (auto j : make_range(4))
956 qa_record[i][j] = qa_storage[i][j].data();
957
958 ex_err = exII::ex_get_qa (ex_id, qa_record.get());
959 EX_CHECK_ERR(ex_err, "Error reading the QA records.");
960
961 // Print the QA records
962 if (verbose)
963 {
964 for (auto i : make_range(num_qa_rec))
965 {
966 libMesh::out << "QA Record: " << i << std::endl;
967 for (auto j : make_range(4))
968 libMesh::out << qa_record[i][j] << std::endl;
969 }
970 }
971 }
972}

References ex_err, ex_id, libMesh::make_range(), libMesh::out, and verbose.

◆ read_sideset()

void libMesh::ExodusII_IO_Helper::read_sideset ( int  id,
int  offset 
)

Reads information about sideset id and inserts it into the global sideset array at the position offset.

Definition at line 1966 of file exodusII_io_helper.C.

1967{
1968 LOG_SCOPE("read_sideset()", "ExodusII_IO_Helper");
1969
1970 libmesh_assert_less (id, ss_ids.size());
1971 libmesh_assert_less (id, num_sides_per_set.size());
1972 libmesh_assert_less (id, num_df_per_set.size());
1973 libmesh_assert_less_equal (offset, elem_list.size());
1974 libmesh_assert_less_equal (offset, side_list.size());
1975
1976 ex_err = exII::ex_get_set_param(ex_id,
1977 exII::EX_SIDE_SET,
1978 ss_ids[id],
1979 &num_sides_per_set[id],
1980 &num_df_per_set[id]);
1981 EX_CHECK_ERR(ex_err, "Error retrieving sideset parameters.");
1982 message("Parameters retrieved successfully for sideset: ", id);
1983
1984
1985 // It's OK for offset==elem_list.size() as long as num_sides_per_set[id]==0
1986 // because in that case we don't actually read anything...
1987#ifdef DEBUG
1988 if (static_cast<unsigned int>(offset) == elem_list.size() ||
1989 static_cast<unsigned int>(offset) == side_list.size() )
1990 libmesh_assert_equal_to (num_sides_per_set[id], 0);
1991#endif
1992
1993
1994 // Don't call ex_get_set unless there are actually sides there to get.
1995 // Exodus prints an annoying warning in DEBUG mode otherwise...
1996 if (num_sides_per_set[id] > 0)
1997 {
1998 ex_err = exII::ex_get_set(ex_id,
1999 exII::EX_SIDE_SET,
2000 ss_ids[id],
2001 &elem_list[offset],
2002 &side_list[offset]);
2003 EX_CHECK_ERR(ex_err, "Error retrieving sideset data.");
2004 message("Data retrieved successfully for sideset: ", id);
2005
2006 for (int i=0; i<num_sides_per_set[id]; i++)
2007 id_list[i+offset] = ss_ids[id];
2008 }
2009}

References elem_list, ex_err, ex_id, id_list, message(), num_df_per_set, num_sides_per_set, side_list, and ss_ids.

Referenced by write_sideset_data().

◆ read_sideset_data()

void libMesh::ExodusII_IO_Helper::read_sideset_data ( const MeshBase &  mesh,
int  timestep,
std::vector< std::string > &  var_names,
std::vector< std::set< boundary_id_type > > &  side_ids,
std::vector< std::map< BoundaryInfo::BCTuple, Real > > &  bc_vals 
)

Read sideset variables, if any, into the provided data structures.

Definition at line 4448 of file exodusII_io_helper.C.

4454{
4455 LOG_SCOPE("read_sideset_data()", "ExodusII_IO_Helper");
4456
4457 // This reads the sideset variable names into the local
4458 // sideset_var_names data structure.
4459 this->read_var_names(SIDESET);
4460
4461 if (num_sideset_vars)
4462 {
4463 // Read the sideset data truth table
4464 std::vector<int> sset_var_tab(num_side_sets * num_sideset_vars);
4465 ex_err = exII::ex_get_truth_table
4466 (ex_id,
4467 exII::EX_SIDE_SET,
4470 sset_var_tab.data());
4471 EX_CHECK_ERR(ex_err, "Error reading sideset variable truth table.");
4472
4473 // Set up/allocate space in incoming data structures.
4474 var_names = sideset_var_names;
4475 side_ids.resize(num_sideset_vars);
4476 bc_vals.resize(num_sideset_vars);
4477
4478 // Read the sideset data.
4479 //
4480 // Note: we assume that read_sideset() has already been called
4481 // for each sideset, so the required values in elem_list and
4482 // side_list are already present.
4483 //
4484 // TODO: As a future optimization, we could read only the values
4485 // requested by the user by looking at the input parameter
4486 // var_names and checking whether it already has entries in
4487 // it. We could do the same thing with the input side_ids
4488 // container and only read values for requested sidesets.
4489 int offset=0;
4490 for (int ss=0; ss<num_side_sets; ++ss)
4491 {
4492 offset += (ss > 0 ? num_sides_per_set[ss-1] : 0);
4493 for (int var=0; var<num_sideset_vars; ++var)
4494 {
4495 int is_present = sset_var_tab[num_sideset_vars*ss + var];
4496
4497 if (is_present)
4498 {
4499 // Record the fact that this variable is defined on this sideset.
4500 side_ids[var].insert(ss_ids[ss]);
4501
4502 // Note: the assumption here is that a previous call
4503 // to this->read_sideset_info() has already set the
4504 // values of num_sides_per_set, so we just use those values here.
4505 std::vector<Real> sset_var_vals(num_sides_per_set[ss]);
4506 ex_err = exII::ex_get_var
4507 (ex_id,
4508 timestep,
4509 exII::EX_SIDE_SET,
4510 var + 1, // 1-based sideset variable index!
4511 ss_ids[ss],
4513 MappedInputVector(sset_var_vals, _single_precision).data());
4514 EX_CHECK_ERR(ex_err, "Error reading sideset variable.");
4515
4516 for (int i=0; i<num_sides_per_set[ss]; ++i)
4517 {
4518 dof_id_type exodus_elem_id = elem_list[i + offset];
4519 unsigned int exodus_side_id = side_list[i + offset];
4520
4521 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4522 // but it apparently is never set up, so just
4523 // subtract 1 from the Exodus elem id.
4524 dof_id_type converted_elem_id = exodus_elem_id - 1;
4525
4526 // Map Exodus side id to libmesh side id.
4527 // Map from Exodus side ids to libmesh side ids.
4528 const auto & conv = get_conversion(mesh.elem_ptr(converted_elem_id)->type());
4529
4530 // Map from Exodus side id to libmesh side id.
4531 // Note: the mapping is defined on 0-based indices, so subtract
4532 // 1 before doing the mapping.
4533 unsigned int converted_side_id = conv.get_side_map(exodus_side_id - 1);
4534
4535 // Make a BCTuple key from the converted information.
4536 BoundaryInfo::BCTuple key = std::make_tuple
4537 (converted_elem_id,
4538 converted_side_id,
4539 ss_ids[ss]);
4540
4541 // Store (elem, side, b_id) tuples in bc_vals[var]
4542 bc_vals[var].emplace(key, sset_var_vals[i]);
4543 } // end for (i)
4544 } // end if (present)
4545 } // end for (var)
4546 } // end for (ss)
4547 } // end if (num_sideset_vars)
4548}
std::vector< std::string > sideset_var_names

References _single_precision, elem_list, libMesh::MeshBase::elem_ptr(), ex_err, ex_id, get_conversion(), mesh, num_side_sets, num_sides_per_set, num_sideset_vars, read_var_names(), side_list, SIDESET, sideset_var_names, ss_ids, and libMesh::Elem::type().

◆ read_sideset_info()

void libMesh::ExodusII_IO_Helper::read_sideset_info ( )

Reads information about all of the sidesets in the ExodusII mesh file.

Definition at line 1862 of file exodusII_io_helper.C.

1863{
1864 ss_ids.resize(num_side_sets);
1865 if (num_side_sets > 0)
1866 {
1867 ex_err = exII::ex_get_ids(ex_id,
1868 exII::EX_SIDE_SET,
1869 ss_ids.data());
1870 EX_CHECK_ERR(ex_err, "Error retrieving sideset information.");
1871 message("All sideset information retrieved successfully.");
1872
1873 // Resize appropriate data structures -- only do this once outside the loop
1876
1877 // Inquire about the length of the concatenated side sets element list
1878 num_elem_all_sidesets = inquire(*this, exII::EX_INQ_SS_ELEM_LEN, "Error retrieving length of the concatenated side sets element list!");
1879
1883 }
1884
1885 char name_buffer[libmesh_max_str_length+1];
1886 for (int i=0; i<num_side_sets; ++i)
1887 {
1888 ex_err = exII::ex_get_name(ex_id, exII::EX_SIDE_SET,
1889 ss_ids[i], name_buffer);
1890 EX_CHECK_ERR(ex_err, "Error getting side set name.");
1891 id_to_ss_names[ss_ids[i]] = name_buffer;
1892 }
1893 message("All side set names retrieved successfully.");
1894}

References elem_list, ex_err, ex_id, id_list, id_to_ss_names, message(), num_df_per_set, num_elem_all_sidesets, num_side_sets, num_sides_per_set, side_list, and ss_ids.

Referenced by write_sideset_data().

◆ read_time_steps()

void libMesh::ExodusII_IO_Helper::read_time_steps ( )

Reads and stores the timesteps in the 'time_steps' array.

Definition at line 2167 of file exodusII_io_helper.C.

2168{
2169 // Make sure we have an up-to-date count of the number of time steps in the file.
2170 this->read_num_time_steps();
2171
2172 if (num_time_steps > 0)
2173 {
2174 time_steps.resize(num_time_steps);
2175 ex_err = exII::ex_get_all_times
2176 (ex_id,
2177 MappedInputVector(time_steps, _single_precision).data());
2178 EX_CHECK_ERR(ex_err, "Error reading timesteps!");
2179 }
2180}

References _single_precision, ex_err, ex_id, num_time_steps, read_num_time_steps(), and time_steps.

◆ read_var_names()

void libMesh::ExodusII_IO_Helper::read_var_names ( ExodusVarType  type)

Definition at line 2256 of file exodusII_io_helper.C.

2257{
2258 switch (type)
2259 {
2260 case NODAL:
2262 break;
2263 case ELEMENTAL:
2265 break;
2266 case GLOBAL:
2268 break;
2269 case SIDESET:
2271 break;
2272 case NODESET:
2274 break;
2275 case ELEMSET:
2277 break;
2278 default:
2279 libmesh_error_msg("Unrecognized ExodusVarType " << type);
2280 }
2281}
virtual void read_var_names_impl(const char *var_type, int &count, std::vector< std::string > &result)
read_var_names() dispatches to this function.

References elem_var_names, ELEMENTAL, ELEMSET, elemset_var_names, GLOBAL, global_var_names, NODAL, nodal_var_names, NODESET, nodeset_var_names, num_elem_vars, num_elemset_vars, num_global_vars, num_nodal_vars, num_nodeset_vars, num_sideset_vars, read_var_names_impl(), SIDESET, and sideset_var_names.

Referenced by check_existing_vars(), read_elemental_var_values(), read_elemset_data(), read_nodal_var_values(), read_nodeset_data(), and read_sideset_data().

◆ read_var_names_impl()

void libMesh::ExodusII_IO_Helper::read_var_names_impl ( const char *  var_type,
int &  count,
std::vector< std::string > &  result 
)
protectedvirtual

read_var_names() dispatches to this function.

We need to override it slightly for Nemesis.

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 2285 of file exodusII_io_helper.C.

2288{
2289 // First read and store the number of names we have
2290 ex_err = exII::ex_get_var_param(ex_id, var_type, &count);
2291 EX_CHECK_ERR(ex_err, "Error reading number of variables.");
2292
2293 // Do nothing if no variables are detected
2294 if (count == 0)
2295 return;
2296
2297 // Second read the actual names and convert them into a format we can use
2298 NamesData names_table(count, libmesh_max_str_length);
2299
2300 ex_err = exII::ex_get_var_names(ex_id,
2301 var_type,
2302 count,
2303 names_table.get_char_star_star()
2304 );
2305 EX_CHECK_ERR(ex_err, "Error reading variable names!");
2306
2307 if (verbose)
2308 {
2309 libMesh::out << "Read the variable(s) from the file:" << std::endl;
2310 for (int i=0; i<count; i++)
2311 libMesh::out << names_table.get_char_star(i) << std::endl;
2312 }
2313
2314 // Allocate enough space for our variable name strings.
2315 result.resize(count);
2316
2317 // Copy the char buffers into strings.
2318 for (int i=0; i<count; i++)
2319 result[i] = names_table.get_char_star(i); // calls string::op=(const char *)
2320}

References ex_err, ex_id, libMesh::ExodusII_IO_Helper::NamesData::get_char_star(), libMesh::ExodusII_IO_Helper::NamesData::get_char_star_star(), libMesh::out, and verbose.

Referenced by read_var_names(), and libMesh::Nemesis_IO_Helper::read_var_names_impl().

◆ set_add_sides()

void libMesh::ExodusII_IO_Helper::set_add_sides ( bool  add_sides)
inline

Sets whether or not to write extra "side" elements.

This is useful for plotting SIDE_DISCONTINUOUS data.

Definition at line 1362 of file exodusII_io_helper.h.

1363{
1364 _add_sides = add_sides;
1365}

References _add_sides.

Referenced by ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl().

◆ set_coordinate_offset()

void libMesh::ExodusII_IO_Helper::set_coordinate_offset ( Point  p)

Allows you to set a vector that is added to the coordinates of all of the nodes.

Effectively, this "moves" the mesh to a particular position

Definition at line 5499 of file exodusII_io_helper.C.

5500{
5502}

References _coordinate_offset.

◆ set_dof_object_unique_id()

void libMesh::ExodusII_IO_Helper::set_dof_object_unique_id ( MeshBase &  mesh,
DofObject *  dof_object,
int  exodus_mapped_id 
)
private

Definition at line 2564 of file exodusII_io_helper.C.

2568{
2569 if (this->set_unique_ids_from_maps)
2570 {
2571 // Exodus ids are always 1-based while libmesh ids are always
2572 // 0-based, so to make a libmesh unique_id here, we subtract 1
2573 // from the exodus_mapped_id to make it 0-based.
2574 auto exodus_mapped_id_zero_based =
2575 cast_int<dof_id_type>(exodus_mapped_id - 1);
2576
2577 // Set added_node's unique_id to "exodus_mapped_id_zero_based".
2578 dof_object->set_unique_id(cast_int<unique_id_type>(exodus_mapped_id_zero_based));
2579
2580 // Normally the Mesh is responsible for setting the unique_ids
2581 // of Nodes/Elems in a consistent manner, so when we set the unique_id
2582 // of a Node/Elem manually based on the {node,elem}_num_map, we need to
2583 // make sure that the "next" unique id assigned by the Mesh
2584 // will still be valid. We do this by making sure that the
2585 // next_unique_id is greater than the one we set manually. The
2586 // APIs for doing this are only defined when unique ids are
2587 // enabled.
2588#ifdef LIBMESH_ENABLE_UNIQUE_ID
2589 unique_id_type next_unique_id = mesh.next_unique_id();
2590 mesh.set_next_unique_id(std::max(next_unique_id, static_cast<unique_id_type>(exodus_mapped_id_zero_based + 1)));
2591#else
2592 // Avoid compiler warnings about the unused variable
2594#endif
2595 }
2596}
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
Definition dof_object.h:862
virtual void set_next_unique_id(unique_id_type id)=0
Sets the next available unique id to be used.
unique_id_type next_unique_id() const
Definition mesh_base.h:607
uint8_t unique_id_type
Definition id_types.h:86
void libmesh_ignore(const Args &...)

References libMesh::libmesh_ignore(), mesh, libMesh::MeshBase::next_unique_id(), libMesh::MeshBase::set_next_unique_id(), libMesh::DofObject::set_unique_id(), and set_unique_ids_from_maps.

Referenced by conditionally_set_elem_unique_id(), and conditionally_set_node_unique_id().

◆ set_hdf5_writing()

void libMesh::ExodusII_IO_Helper::set_hdf5_writing ( bool  write_hdf5)

Set to true (the default) to write files in an HDF5-based file format (when HDF5 is available), or to false to write files in the old NetCDF3-based format.

If HDF5 is unavailable, this setting does nothing.

Definition at line 5472 of file exodusII_io_helper.C.

5473{
5474 _write_hdf5 = write_hdf5;
5475}

References _write_hdf5.

◆ set_max_name_length()

void libMesh::ExodusII_IO_Helper::set_max_name_length ( unsigned int  max_length)

Set how many characters to use in names when opening a file for writing.

Definition at line 5478 of file exodusII_io_helper.C.

5479{
5480 // Opt mode error, because this may be exposed to users
5481 libmesh_error_msg_if (max_length > libmesh_max_str_length,
5482 "Exodus maximum name length is limited to " <<
5483 libmesh_max_str_length << " characters");
5484
5485 // Devel+dbg mode assertion, because developers should do better
5487
5488 _max_name_length = max_length;
5489}

References _max_name_length, libMesh::libmesh_assert(), and opened_for_writing.

◆ update()

void libMesh::ExodusII_IO_Helper::update ( )

Uses ex_update() to flush buffers to file.

Definition at line 5437 of file exodusII_io_helper.C.

5438{
5439 ex_err = exII::ex_update(ex_id);
5440 EX_CHECK_ERR(ex_err, "Error flushing buffers to file.");
5441}

References ex_err, and ex_id.

Referenced by libMesh::Nemesis_IO_Helper::write_element_values(), write_element_values(), write_element_values_element_major(), write_global_values(), write_information_records(), write_nodal_values(), and write_timestep().

◆ use_mesh_dimension_instead_of_spatial_dimension()

void libMesh::ExodusII_IO_Helper::use_mesh_dimension_instead_of_spatial_dimension ( bool  val)

Sets the underlying value of the boolean flag _use_mesh_dimension_instead_of_spatial_dimension.

By default, the value of this flag is false.

See the ExodusII_IO class documentation for a detailed description of this flag.

Definition at line 5466 of file exodusII_io_helper.C.

References _use_mesh_dimension_instead_of_spatial_dimension.

◆ write_as_dimension()

void libMesh::ExodusII_IO_Helper::write_as_dimension ( unsigned  dim)

Sets the value of _write_as_dimension.

This directly controls the num_dim which is written to the Exodus file. If non-zero, this value supersedes all other dimensions, including: 1.) MeshBase::spatial_dimension() 2.) MeshBase::mesh_dimension() 3.) Any value passed to use_mesh_dimension_instead_of_spatial_dimension() This is useful/necessary for working around a bug in Paraview which prevents the "Plot Over Line" filter from working on 1D meshes.

Definition at line 5492 of file exodusII_io_helper.C.

5493{
5495}

References _write_as_dimension, and dim.

◆ write_element_values()

void libMesh::ExodusII_IO_Helper::write_element_values ( const MeshBase &  mesh,
const std::vector< Real > &  values,
int  timestep,
const std::vector< std::set< subdomain_id_type > > &  vars_active_subdomains 
)

Writes the vector of values to the element variables.

The 'values' vector is assumed to be in the order: {(u1, u2, u3, ..., uN), (v1, v2, v3, ..., vN), (w1, w2, w3, ..., wN)} where N is the number of elements.

This ordering is produced by calls to ES::build_elemental_solution_vector(). ES::build_discontinuous_solution_vector(), on the other hand, produces an element-major ordering. See the function below for that case.

Definition at line 5124 of file exodusII_io_helper.C.

5129{
5130 LOG_SCOPE("write_element_values()", "ExodusII_IO_Helper");
5131
5132 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5133 return;
5134
5135 // Ask the file how many element vars it has, store it in the num_elem_vars variable.
5136 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_BLOCK, &num_elem_vars);
5137 EX_CHECK_ERR(ex_err, "Error reading number of elemental variables.");
5138
5139 // We will eventually loop over the element blocks (subdomains) and
5140 // write the data one block at a time. Build a data structure that
5141 // maps each subdomain to a list of element ids it contains.
5142 std::map<subdomain_id_type, std::vector<unsigned int>> subdomain_map;
5143 for (const auto & elem : mesh.active_element_ptr_range())
5144 subdomain_map[elem->subdomain_id()].push_back(elem->id());
5145
5146 // Use mesh.n_elem() to access into the values vector rather than
5147 // the number of elements the Exodus writer thinks the mesh has,
5148 // which may not include inactive elements.
5150
5151 // Sanity check: we must have an entry in vars_active_subdomains for
5152 // each variable that we are potentially writing out.
5153 libmesh_assert_equal_to
5154 (vars_active_subdomains.size(),
5155 static_cast<unsigned>(num_elem_vars));
5156
5157 // For each variable, create a 'data' array which holds all the elemental variable
5158 // values *for a given block* on this processor, then write that data vector to file
5159 // before moving onto the next block.
5160 for (unsigned int var_id=0; var_id<static_cast<unsigned>(num_elem_vars); ++var_id)
5161 {
5162 // The size of the subdomain map is the number of blocks.
5163 auto it = subdomain_map.begin();
5164
5165 // Reference to the set of active subdomains for the current variable.
5166 const auto & active_subdomains
5167 = vars_active_subdomains[var_id];
5168
5169 for (unsigned int j=0; it!=subdomain_map.end(); ++it, ++j)
5170 {
5171 // Skip any variable/subdomain pairs that are inactive.
5172 // Note that if active_subdomains is empty, it is interpreted
5173 // as being active on *all* subdomains.
5174 if (!(active_subdomains.empty() || active_subdomains.count(it->first)))
5175 continue;
5176
5177 // Get reference to list of elem ids which are in the
5178 // current subdomain and count, allocate storage to hold
5179 // data that will be written to file.
5180 const auto & elem_nums = it->second;
5181 const unsigned int num_elems_this_block =
5182 cast_int<unsigned int>(elem_nums.size());
5183 std::vector<Real> data(num_elems_this_block);
5184
5185 // variable-major ordering is:
5186 // (u1, u2, u3, ..., uN), (v1, v2, v3, ..., vN), ...
5187 // where N is the number of elements.
5188 for (unsigned int k=0; k<num_elems_this_block; ++k)
5189 data[k] = values[var_id*n_elem + elem_nums[k]];
5190
5191 ex_err = exII::ex_put_var
5192 (ex_id,
5193 timestep,
5194 exII::EX_ELEM_BLOCK,
5195 var_id+1,
5196 this->get_block_id(j),
5197 num_elems_this_block,
5198 MappedOutputVector(data, _single_precision).data());
5199
5200 EX_CHECK_ERR(ex_err, "Error writing element values.");
5201 }
5202 }
5203
5204 this->update();
5205}
void update()
Uses ex_update() to flush buffers to file.
int get_block_id(int index)
Get the block number for the given block index.
virtual dof_id_type n_elem() const =0
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).

References _run_only_on_proc0, _single_precision, ex_err, ex_id, get_block_id(), libMesh::DofObject::id(), mesh, libMesh::MeshBase::n_elem(), num_elem_vars, libMesh::ParallelObject::processor_id(), libMesh::Elem::subdomain_id(), and update().

◆ write_element_values_element_major()

void libMesh::ExodusII_IO_Helper::write_element_values_element_major ( const MeshBase &  mesh,
const std::vector< Real > &  values,
int  timestep,
const std::vector< std::set< subdomain_id_type > > &  vars_active_subdomains,
const std::vector< std::string > &  derived_var_names,
const std::map< subdomain_id_type, std::vector< std::string > > &  subdomain_to_var_names 
)

Same as the function above, but assume the input 'values' vector is in element-major order, i.e.

{(u1,v1,w1), (u2,v2,w2), ... (uN,vN,wN)} This function is called by ExodusII_IO::write_element_data_from_discontinuous_nodal_data() because ES::build_discontinuous_solution_vector() builds the solution vector in this order.

Note
If some variables are subdomain-restricted, then the tuples will be of different lengths for each element, i.e. {(u1,v1,w1), (u2,v2), ... (uN,vN,wN)} if variable w is not active on element 2.

Definition at line 5209 of file exodusII_io_helper.C.

5216{
5217 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5218 return;
5219
5220 // Ask the file how many element vars it has, store it in the num_elem_vars variable.
5221 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_BLOCK, &num_elem_vars);
5222 EX_CHECK_ERR(ex_err, "Error reading number of elemental variables.");
5223
5224 // We will eventually loop over the element blocks (subdomains) and
5225 // write the data one block (subdomain) at a time. Build a data
5226 // structure that keeps track of how many elements are in each
5227 // subdomain. This will allow us to reserve space in the data vector
5228 // we are going to write.
5229 std::map<subdomain_id_type, unsigned int> subdomain_to_n_elem;
5230 for (const auto & elem : mesh.active_element_ptr_range())
5231 subdomain_to_n_elem[elem->subdomain_id()] += 1;
5232
5233 // Sanity check: we must have an entry in vars_active_subdomains for
5234 // each variable that we are potentially writing out.
5235 libmesh_assert_equal_to
5236 (vars_active_subdomains.size(),
5237 static_cast<unsigned>(num_elem_vars));
5238
5239 // The size of the subdomain map is the number of blocks.
5240 auto subdomain_to_n_elem_iter = subdomain_to_n_elem.begin();
5241
5242 // Store range of active Elem pointers. We are going to loop over
5243 // the elements n_vars * n_subdomains times, so let's make sure
5244 // the predicated iterators aren't slowing us down too much.
5245 ConstElemRange elem_range
5246 (mesh.active_elements_begin(),
5247 mesh.active_elements_end());
5248
5249 for (unsigned int sbd_idx=0;
5250 subdomain_to_n_elem_iter != subdomain_to_n_elem.end();
5251 ++subdomain_to_n_elem_iter, ++sbd_idx)
5252 for (unsigned int var_id=0; var_id<static_cast<unsigned>(num_elem_vars); ++var_id)
5253 {
5254 // Reference to the set of active subdomains for the current variable.
5255 const auto & active_subdomains
5256 = vars_active_subdomains[var_id];
5257
5258 // If the vars_active_subdomains container passed to this function
5259 // has an empty entry, it means the variable really is not active on
5260 // _any_ subdomains, not that it is active on _all_ subdomains. This
5261 // is just due to the way that we build the vars_active_subdomains
5262 // container.
5263 if (!active_subdomains.count(subdomain_to_n_elem_iter->first))
5264 continue;
5265
5266 // Vector to hold values that will be written to Exodus file.
5267 std::vector<Real> data;
5268 data.reserve(subdomain_to_n_elem_iter->second);
5269
5270 unsigned int values_offset = 0;
5271 for (auto & elem : elem_range)
5272 {
5273 // We'll use the Elem's subdomain id in several places below.
5274 subdomain_id_type sbd_id = elem->subdomain_id();
5275
5276 // Get reference to the list of variable names defining
5277 // the indexing for the current Elem's subdomain.
5278 auto subdomain_to_var_names_iter =
5279 subdomain_to_var_names.find(sbd_id);
5280
5281 // It's possible, but unusual, for there to be an Elem
5282 // from a subdomain that has no active variables from the
5283 // set of variables we are currently writing. If that
5284 // happens, we can just go to the next Elem because we
5285 // don't need to advance the offset into the values
5286 // vector, etc.
5287 if (subdomain_to_var_names_iter == subdomain_to_var_names.end())
5288 continue;
5289
5290 const auto & var_names_this_sbd
5291 = subdomain_to_var_names_iter->second;
5292
5293 // Only extract values if Elem is in the current subdomain.
5294 if (sbd_id == subdomain_to_n_elem_iter->first)
5295 {
5296 // Location of current var_id in the list of all variables on this
5297 // subdomain. FIXME: linear search but it's over a typically relatively
5298 // short vector of active variable names on this subdomain. We could do
5299 // a nested std::map<string,index> instead of a std::vector where the
5300 // location of the string is implicitly the index..
5301 auto pos =
5302 std::find(var_names_this_sbd.begin(),
5303 var_names_this_sbd.end(),
5304 derived_var_names[var_id]);
5305
5306 libmesh_error_msg_if(pos == var_names_this_sbd.end(),
5307 "Derived name " << derived_var_names[var_id] << " not found!");
5308
5309 // Find the current variable's location in the list of all variable
5310 // names on the current Elem's subdomain.
5311 auto true_index =
5312 std::distance(var_names_this_sbd.begin(), pos);
5313
5314 data.push_back(values[values_offset + true_index]);
5315 }
5316
5317 // The "true" offset is how much we have to advance the index for each Elem
5318 // in this subdomain.
5319 auto true_offset = var_names_this_sbd.size();
5320
5321 // Increment to the next Elem's values
5322 values_offset += true_offset;
5323 } // for elem
5324
5325 // Now write 'data' to Exodus file, in single precision if requested.
5326 if (!data.empty())
5327 {
5328 ex_err = exII::ex_put_var
5329 (ex_id,
5330 timestep,
5331 exII::EX_ELEM_BLOCK,
5332 var_id+1,
5333 this->get_block_id(sbd_idx),
5334 data.size(),
5335 MappedOutputVector(data, _single_precision).data());
5336
5337 EX_CHECK_ERR(ex_err, "Error writing element values.");
5338 }
5339 } // for each var_id
5340
5341 this->update();
5342}
The StoredRange class defines a contiguous, divisible set of objects.

References _run_only_on_proc0, _single_precision, ex_err, ex_id, get_block_id(), mesh, num_elem_vars, libMesh::ParallelObject::processor_id(), libMesh::Elem::subdomain_id(), and update().

◆ write_elements()

void libMesh::ExodusII_IO_Helper::write_elements ( const MeshBase &  mesh,
bool  use_discontinuous = false 
)
virtual

Writes the elements contained in "mesh".

FIXME: This only works for Meshes having a single type of element in each subdomain!

If use_discontinuous is true, we break apart elements, so that shared nodes on faces/edges/vertices can take different values from different elements. This is useful for plotting discontinuous underlying variables

If _add_sides is true, we also output side elements, so that shared nodes on edges/vertices can take different values from different elements. This is useful for plotting SIDE_DISCONTINUOUS representing e.g. inter-element fluxes.

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 3046 of file exodusII_io_helper.C.

3047{
3048 LOG_SCOPE("write_elements()", "ExodusII_IO_Helper");
3049
3050 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3051 return;
3052
3053 // Map from block ID to a vector of element IDs in that block. Element
3054 // IDs are now of type dof_id_type, subdomain IDs are of type subdomain_id_type.
3055 subdomain_id_type subdomain_id_end = 0;
3056 auto subdomain_map = build_subdomain_map(mesh,
3057 _add_sides,
3058 /*reduce=*/!_run_only_on_proc0,
3059 subdomain_id_end);
3060
3061 // Allocate the polyhedron face block ID after both mesh subdomains and
3062 // any blocks synthesized for visualization sides.
3063 const int c0polyhedron_face_block_id = subdomain_map.empty() ? 0 :
3064 cast_int<int>(subdomain_map.rbegin()->first) + 1;
3065
3066 // element map vector
3067 num_elem_blk = cast_int<int>(subdomain_map.size());
3068 block_ids.resize(num_elem_blk);
3069
3070 std::vector<int> elem_blk_id;
3071 std::vector<int> num_elem_this_blk_vec;
3072 std::vector<int> num_nodes_per_elem_vec;
3073 std::vector<int> num_edges_per_elem_vec;
3074 std::vector<int> num_faces_per_elem_vec;
3075 std::vector<int> num_attr_vec;
3076 NamesData elem_type_table(num_elem_blk, _max_name_length);
3077
3078 // Note: It appears that there is a bug in exodusII::ex_put_name where
3079 // the index returned from the ex_id_lkup is erroneously used. For now
3080 // the work around is to use the alternative function ex_put_names, but
3081 // this function requires a char ** data structure.
3082 NamesData names_table(num_elem_blk, _max_name_length);
3083
3084 num_elem = 0;
3085 bool has_c0polygon_blocks = false;
3086 bool has_c0polyhedron_blocks = false;
3087 int c0polyhedron_total_faces = 0;
3088 int c0polyhedron_total_face_nodes = 0;
3089
3090 // counter indexes into the block_ids vector
3091 unsigned int counter = 0;
3092 for (auto & [subdomain_id, element_id_vec] : subdomain_map)
3093 {
3094 block_ids[counter] = subdomain_id;
3095
3096 const ElemType elem_t = (subdomain_id >= subdomain_id_end) ?
3097 ElemType(subdomain_id - subdomain_id_end) :
3098 mesh.elem_ref(element_id_vec[0]).type();
3099
3100 if (subdomain_id >= subdomain_id_end)
3101 {
3103 libmesh_assert(element_id_vec.size() == 1);
3104 num_elem_this_blk_vec.push_back
3105 (cast_int<int>(element_id_vec[0]));
3106 names_table.push_back_entry
3107 (Utility::enum_to_string<ElemType>(elem_t));
3108 }
3109 else
3110 {
3111 libmesh_assert(!element_id_vec.empty());
3112 num_elem_this_blk_vec.push_back
3113 (cast_int<int>(element_id_vec.size()));
3114
3115 // A block id normally *is* a subdomain id, but a subdomain that
3116 // contains more than one element type is split across several
3117 // blocks by build_subdomain_map(): only its first element type
3118 // keeps the subdomain id, while every other type gets a
3119 // synthesized block id allocated above all subdomain ids. We
3120 // detect such synthesized blocks from the mismatch between the
3121 // block id and the actual subdomain of the elements it holds.
3122 const subdomain_id_type elem_subdomain_id =
3123 mesh.elem_ref(element_id_vec[0]).subdomain_id();
3124 const bool is_synthesized_block = (subdomain_id != elem_subdomain_id);
3125
3126 std::string block_name = mesh.subdomain_name(elem_subdomain_id);
3127
3128 if (is_synthesized_block)
3129 {
3130 // Suffix the (original) subdomain's name with the element
3131 // type, so the synthesized block is identifiable and its
3132 // name stays distinct from the block that kept the
3133 // subdomain id. This block becomes its own subdomain when
3134 // the file is read back in.
3135 const std::string type_suffix = Utility::enum_to_string<ElemType>(elem_t);
3136 block_name = block_name.empty()
3137 ? (std::to_string(elem_subdomain_id) + "_" + type_suffix)
3138 : (block_name + "_" + type_suffix);
3139
3140 // Informational: keep it to one rank so parallel (Nemesis)
3141 // writes will not repeat it once per processor.
3142 // NOTE this might miss logs if only occurs on other ranks
3143 if (this->processor_id() == 0)
3144 libMesh::out << "ExodusII_IO: subdomain " << elem_subdomain_id
3145 << " contains more than one element type; writing its "
3146 << type_suffix << " elements to a new block \"" << block_name
3147 << "\" (block id " << subdomain_id
3148 << ")"
3149 << std::endl;
3150 }
3151
3152 if (block_name.empty() && elem_t == C0POLYGON)
3153 block_name = "NSIDED_" + std::to_string(counter + 1);
3154 if (block_name.empty() && elem_t == C0POLYHEDRON)
3155 block_name = "NFACED_" + std::to_string(counter + 1);
3156 names_table.push_back_entry(block_name);
3157 }
3158
3159 num_elem += num_elem_this_blk_vec.back();
3160
3161 // Use the first element in this block to get representative information.
3162 // Note that Exodus assumes all elements in a block are of the same type!
3163 // We are using that same assumption here!
3164 const auto & conv = get_conversion(elem_t);
3165 int num_edges_per_elem = 0;
3166 int num_faces_per_elem = 0;
3167 if (elem_t == C0POLYGON)
3168 {
3169 if (subdomain_id >= subdomain_id_end)
3170 libmesh_not_implemented_msg("Support for C0POLYGON side blocks not yet implemented");
3171
3172 has_c0polygon_blocks = true;
3174
3175 for (auto elem_id : element_id_vec)
3176 {
3177 const Elem & elem = mesh.elem_ref(elem_id);
3178
3179 libmesh_error_msg_if(elem.type() != C0POLYGON,
3180 "Error: Exodus requires all elements with a given subdomain ID "
3181 "to be the same type.\n"
3182 << "Can't write both "
3183 << Utility::enum_to_string(elem.type())
3184 << " and C0POLYGON in the same block!");
3185
3186 num_nodes_per_elem += cast_int<int>(elem.n_nodes());
3187 }
3188 }
3189 else if (elem_t == C0POLYHEDRON)
3190 {
3191 if (subdomain_id >= subdomain_id_end)
3192 libmesh_not_implemented_msg("Support for C0POLYHEDRON side blocks not yet implemented");
3193
3194 has_c0polyhedron_blocks = true;
3196
3197 for (auto elem_id : element_id_vec)
3198 {
3199 const Elem & elem = mesh.elem_ref(elem_id);
3200
3201 libmesh_error_msg_if(elem.type() != C0POLYHEDRON,
3202 "Error: Exodus requires all elements with a given subdomain ID "
3203 "to be the same type.\n"
3204 << "Can't write both "
3205 << Utility::enum_to_string(elem.type())
3206 << " and C0POLYHEDRON in the same block!");
3207
3208 const int elem_n_sides = cast_int<int>(elem.n_sides());
3209 num_faces_per_elem += elem_n_sides;
3210 c0polyhedron_total_faces += elem_n_sides;
3211
3212 for (auto s : elem.side_index_range())
3213 c0polyhedron_total_face_nodes += cast_int<int>(elem.nodes_on_side(s).size());
3214 }
3215 }
3216 else
3217 {
3220 libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
3221 }
3222
3223 elem_blk_id.push_back(subdomain_id);
3224 elem_type_table.push_back_entry(conv.exodus_elem_type().c_str());
3225 num_nodes_per_elem_vec.push_back(num_nodes_per_elem);
3226 num_attr_vec.push_back(0); // we don't currently use elem block attributes.
3227 num_edges_per_elem_vec.push_back(num_edges_per_elem); // We don't currently store any edge blocks
3228 num_faces_per_elem_vec.push_back(num_faces_per_elem);
3229 ++counter;
3230 }
3231
3232 if (has_c0polyhedron_blocks)
3233 {
3234 libmesh_assert_equal_to(num_face_blk, 1);
3235 libmesh_assert_equal_to(num_face, c0polyhedron_total_faces);
3236 }
3237
3238 // Here we reserve() space so that we can push_back() onto the
3239 // elem_num_map in the loops below.
3240 this->elem_num_map.reserve(num_elem);
3241
3242 // In the case of discontinuous plotting we initialize a map from
3243 // (element, node) pairs to the corresponding discontinuous node index.
3244 // This ordering must match the ordering used in write_nodal_coordinates.
3245 //
3246 // Note: This map takes the place of the libmesh_node_num_to_exodus map in
3247 // the discontinuous case.
3248 std::map<std::pair<dof_id_type, unsigned int>, dof_id_type> discontinuous_node_indices;
3249 dof_id_type node_counter = 1; // Exodus numbering is 1-based
3250 if (use_discontinuous)
3251 {
3252 for (const auto & elem : mesh.active_element_ptr_range())
3253 for (auto n : elem->node_index_range())
3254 discontinuous_node_indices[std::make_pair(elem->id(),n)] =
3255 node_counter++;
3256 }
3257 else
3258 node_counter = mesh.max_node_id() + 1; // Exodus numbering is 1-based
3259
3260 if (_add_sides)
3261 {
3262 for (const Elem * elem : mesh.active_element_ptr_range())
3263 {
3264 // We'll use "past-the-end" indices to indicate side node
3265 // copies
3266 unsigned int local_node_index = elem->n_nodes();
3267
3268 for (auto s : elem->side_index_range())
3269 {
3271 continue;
3272
3273 const std::vector<unsigned int> side_nodes =
3274 elem->nodes_on_side(s);
3275
3276 for (auto n : index_range(side_nodes))
3277 {
3278 libmesh_ignore(n);
3279 discontinuous_node_indices
3280 [std::make_pair(elem->id(),local_node_index++)] =
3281 node_counter++;
3282 }
3283 }
3284 }
3285 }
3286
3287 // Reference to the BoundaryInfo object for convenience.
3288 const BoundaryInfo & bi = mesh.get_boundary_info();
3289
3290 // Build list of (elem, edge, id) triples
3291 std::vector<BoundaryInfo::BCTuple> edge_tuples = bi.build_edge_list();
3292
3293 // Build the connectivity array for each edge block. The connectivity array
3294 // is a vector<int> with "num_edges * num_nodes_per_edge" entries. We write
3295 // the Exodus node numbers to the connectivity arrays so that they can
3296 // be used directly in the calls to exII::ex_put_conn() below. We also keep
3297 // track of the ElemType and the number of nodes for each boundary_id. All
3298 // edges with a given boundary_id must be of the same type.
3299 std::map<boundary_id_type, std::vector<int>> edge_id_to_conn;
3300 std::map<boundary_id_type, std::pair<ElemType, unsigned int>> edge_id_to_elem_type;
3301
3302 std::unique_ptr<const Elem> edge;
3303 for (const auto & t : edge_tuples)
3304 {
3305 dof_id_type elem_id = std::get<0>(t);
3306 unsigned int edge_id = std::get<1>(t);
3307 boundary_id_type b_id = std::get<2>(t);
3308
3309 // Build the edge in question
3310 mesh.elem_ptr(elem_id)->build_edge_ptr(edge, edge_id);
3311
3312 // Error checking: make sure that all edges in this block are
3313 // the same geometric type.
3314 if (const auto check_it = edge_id_to_elem_type.find(b_id);
3315 check_it == edge_id_to_elem_type.end())
3316 {
3317 // Keep track of the ElemType and number of nodes in this boundary id.
3318 edge_id_to_elem_type[b_id] = std::make_pair(edge->type(), edge->n_nodes());
3319 }
3320 else
3321 {
3322 // Make sure the existing data is consistent
3323 const auto & val_pair = check_it->second;
3324 libmesh_error_msg_if(val_pair.first != edge->type() || val_pair.second != edge->n_nodes(),
3325 "All edges in a block must have same geometric type.");
3326 }
3327
3328 // Get reference to the connectivity array for this block
3329 auto & conn = edge_id_to_conn[b_id];
3330
3331 // For each node on the edge, look up the exodus node id and
3332 // store it in the conn array. Note: all edge types have
3333 // identity node mappings so we don't bother with Conversion
3334 // objects here.
3335 for (auto n : edge->node_index_range())
3336 {
3337 // We look up Exodus node numbers differently if we are
3338 // writing a discontinuous Exodus file.
3339 int exodus_node_id = -1;
3340
3341 if (!use_discontinuous)
3342 {
3343 dof_id_type libmesh_node_id = edge->node_ptr(n)->id();
3344 exodus_node_id = libmesh_map_find
3345 (libmesh_node_num_to_exodus, cast_int<int>(libmesh_node_id));
3346 }
3347 else
3348 {
3349 // Get the node on the element containing this edge
3350 // which corresponds to edge node n. Then use that id to look up
3351 // the exodus_node_id in the discontinuous_node_indices map.
3352 unsigned int pn = mesh.elem_ptr(elem_id)->local_edge_node(edge_id, n);
3353 exodus_node_id = libmesh_map_find
3354 (discontinuous_node_indices, std::make_pair(elem_id, pn));
3355 }
3356
3357 conn.push_back(exodus_node_id);
3358 }
3359 }
3360
3361 // Make sure we have the same number of edge ids that we thought we would.
3362 libmesh_assert(static_cast<int>(edge_id_to_conn.size()) == num_edge_blk);
3363
3364 // Build data structures describing edge blocks. This information must be
3365 // be passed to exII::ex_put_concat_all_blocks() at the same time as the
3366 // information about elem blocks.
3367 std::vector<int> edge_blk_id;
3368 NamesData edge_type_table(num_edge_blk, _max_name_length);
3369 std::vector<int> num_edge_this_blk_vec;
3370 std::vector<int> num_nodes_per_edge_vec;
3371 std::vector<int> num_attr_edge_vec;
3372
3373 // We also build a data structure of edge block names which can
3374 // later be passed to exII::ex_put_names().
3375 NamesData edge_block_names_table(num_edge_blk, _max_name_length);
3376 NamesData face_block_names_table(num_face_blk, _max_name_length);
3377 if (has_c0polyhedron_blocks)
3378 face_block_names_table.push_back_entry("NSIDED_FACES");
3379
3380 // Note: We are going to use the edge **boundary** ids as **block** ids.
3381 for (const auto & pr : edge_id_to_conn)
3382 {
3383 // Store the edge block id in the array to be passed to Exodus.
3384 boundary_id_type id = pr.first;
3385 edge_blk_id.push_back(id);
3386
3387 // Set Exodus element type and number of nodes for this edge block.
3388 const auto & elem_type_node_count = edge_id_to_elem_type[id];
3389 const auto & conv = get_conversion(elem_type_node_count.first);
3390 edge_type_table.push_back_entry(conv.exodus_type.c_str());
3391 num_nodes_per_edge_vec.push_back(elem_type_node_count.second);
3392
3393 // The number of edges is the number of entries in the connectivity
3394 // array divided by the number of nodes per edge.
3395 num_edge_this_blk_vec.push_back(pr.second.size() / elem_type_node_count.second);
3396
3397 // We don't store any attributes currently
3398 num_attr_edge_vec.push_back(0);
3399
3400 // Store the name of this edge block
3401 edge_block_names_table.push_back_entry(bi.get_edgeset_name(id));
3402 }
3403
3404 if (has_c0polygon_blocks || has_c0polyhedron_blocks)
3405 {
3406 // ex_put_concat_all_blocks() does not define the per-polytope
3407 // entity count arrays required by NSIDED/NFACED blocks in all supported
3408 // Exodus versions. Define blocks individually through ex_put_block().
3409 if (has_c0polyhedron_blocks)
3410 {
3411 ex_err = exII::ex_put_block(ex_id,
3412 exII::EX_FACE_BLOCK,
3413 c0polyhedron_face_block_id,
3414 "NSIDED",
3415 c0polyhedron_total_faces,
3416 c0polyhedron_total_face_nodes,
3417 0,
3418 0,
3419 0);
3420 EX_CHECK_ERR(ex_err, "Error writing polyhedron face block.");
3421 }
3422
3423 for (auto i : index_range(elem_blk_id))
3424 {
3425 ex_err = exII::ex_put_block(ex_id,
3426 exII::EX_ELEM_BLOCK,
3427 elem_blk_id[i],
3428 elem_type_table.get_char_star(cast_int<int>(i)),
3429 num_elem_this_blk_vec[i],
3430 num_nodes_per_elem_vec[i],
3431 num_edges_per_elem_vec[i],
3432 num_faces_per_elem_vec[i],
3433 num_attr_vec[i]);
3434 EX_CHECK_ERR(ex_err, "Error writing element block.");
3435 }
3436
3437 for (auto i : index_range(edge_blk_id))
3438 {
3439 ex_err = exII::ex_put_block(ex_id,
3440 exII::EX_EDGE_BLOCK,
3441 edge_blk_id[i],
3442 edge_type_table.get_char_star(cast_int<int>(i)),
3443 num_edge_this_blk_vec[i],
3444 num_nodes_per_edge_vec[i],
3445 0,
3446 0,
3447 num_attr_edge_vec[i]);
3448 EX_CHECK_ERR(ex_err, "Error writing edge block.");
3449 }
3450 }
3451 else
3452 {
3453 // Zero-initialize and then fill in an exII::ex_block_params struct
3454 // with the data we have collected. This new API replaces the old
3455 // exII::ex_put_concat_elem_block() API, and will eventually allow
3456 // us to also allocate space for edge/face blocks if desired.
3457 //
3458 // TODO: It seems like we should be able to take advantage of the
3459 // optimization where you set define_maps==1, but when I tried this
3460 // I got the error: "failed to find node map size". I think the
3461 // problem is that we need to first specify a nonzero number of
3462 // node/elem maps during the call to ex_put_init_ext() in order for
3463 // this to work correctly.
3464 exII::ex_block_params params = {};
3465
3466 // Set pointers for information about elem blocks.
3467 params.elem_blk_id = elem_blk_id.data();
3468 params.elem_type = elem_type_table.get_char_star_star();
3469 params.num_elem_this_blk = num_elem_this_blk_vec.data();
3470 params.num_nodes_per_elem = num_nodes_per_elem_vec.data();
3471 params.num_edges_per_elem = num_edges_per_elem_vec.data();
3472 params.num_faces_per_elem = num_faces_per_elem_vec.data();
3473 params.num_attr_elem = num_attr_vec.data();
3474 params.define_maps = 0;
3475
3476 // Set pointers to edge block information only if we actually have some.
3477 if (num_edge_blk)
3478 {
3479 params.edge_blk_id = edge_blk_id.data();
3480 params.edge_type = edge_type_table.get_char_star_star();
3481 params.num_edge_this_blk = num_edge_this_blk_vec.data();
3482 params.num_nodes_per_edge = num_nodes_per_edge_vec.data();
3483 params.num_attr_edge = num_attr_edge_vec.data();
3484 }
3485
3486 ex_err = exII::ex_put_concat_all_blocks(ex_id, &params);
3487 EX_CHECK_ERR(ex_err, "Error writing element blocks.");
3488 }
3489
3490 // This counter is used to fill up the libmesh_elem_num_to_exodus map in the loop below.
3491 unsigned libmesh_elem_num_to_exodus_counter = 0;
3492
3493 // We need these later if we're adding fake sides, but we don't need
3494 // to recalculate it.
3495 auto num_elem_this_blk_it = num_elem_this_blk_vec.begin();
3496
3497 // We write "fake" ids to the elem_num_map when adding fake sides.
3498 // I don't think it's too important exactly what fake ids are used,
3499 // as long as they don't conflict with any other ids that are
3500 // already in the elem_num_map.
3501 auto next_fake_id = mesh.max_elem_id() + 1; // 1-based numbering in Exodus
3502#ifdef LIBMESH_ENABLE_UNIQUE_ID
3503 if (this->set_unique_ids_from_maps)
3504 next_fake_id = mesh.next_unique_id();
3505#endif
3506
3507 std::vector<int> face_connect;
3508 std::vector<int> c0polyhedron_face_node_counts;
3509 face_connect.reserve(c0polyhedron_total_face_nodes);
3510 c0polyhedron_face_node_counts.reserve(c0polyhedron_total_faces);
3511 int next_c0polyhedron_face_id = 1;
3512
3513 const auto get_exodus_node_id = [&](const Elem &elem,
3514 dof_id_type elem_id,
3515 unsigned int elem_node_index)
3516 -> int
3517 {
3518 if (!use_discontinuous)
3519 return libmesh_map_find(libmesh_node_num_to_exodus,
3520 cast_int<int>(elem.node_id(elem_node_index)));
3521
3522 return cast_int<int>(libmesh_map_find(discontinuous_node_indices,
3523 std::make_pair(elem_id, elem_node_index)));
3524 };
3525
3526 for (auto & [subdomain_id, element_id_vec] : subdomain_map)
3527 {
3528 // Use the first element in the block to get representative
3529 // information for a "real" block. Note that Exodus assumes all
3530 // elements in a block are of the same type! We are using that
3531 // same assumption here!
3532 const ElemType elem_t = (subdomain_id >= subdomain_id_end) ?
3533 ElemType(subdomain_id - subdomain_id_end) :
3534 mesh.elem_ref(element_id_vec[0]).type();
3535
3536 const auto & conv = get_conversion(elem_t);
3537 const bool is_c0polygon_block = (elem_t == C0POLYGON);
3538 const bool is_c0polyhedron_block = (elem_t == C0POLYHEDRON);
3539 const bool is_variable_connectivity_block =
3540 is_c0polygon_block || is_c0polyhedron_block;
3541 std::vector<int> c0polygon_node_counts;
3542 std::vector<int> c0polyhedron_face_counts;
3543
3544 if (is_variable_connectivity_block && subdomain_id >= subdomain_id_end)
3545 libmesh_not_implemented_msg("Support for " <<
3546 Utility::enum_to_string(elem_t) <<
3547 " side blocks not yet implemented");
3548
3549 if (!is_variable_connectivity_block)
3550 {
3553 libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
3554 }
3555
3556 // If this is a *real* block, we just loop over vectors of
3557 // element ids to add.
3558 if (subdomain_id < subdomain_id_end)
3559 {
3560 if (is_variable_connectivity_block)
3561 connect.clear();
3562 if (is_c0polygon_block)
3563 c0polygon_node_counts.reserve(element_id_vec.size());
3564 else if (is_c0polyhedron_block)
3565 c0polyhedron_face_counts.reserve(element_id_vec.size());
3566 else
3567 connect.resize(element_id_vec.size()*num_nodes_per_elem);
3568
3569 const auto add_c0polygon_connectivity =
3570 [&](const Elem &elem, dof_id_type elem_id)
3571 {
3572 c0polygon_node_counts.push_back(cast_int<int>(elem.n_nodes()));
3573 for (auto elem_node_index : elem.node_index_range())
3574 connect.push_back(get_exodus_node_id(elem, elem_id, elem_node_index));
3575
3576 };
3577
3578 const auto add_c0polyhedron_connectivity =
3579 [&](const Elem &elem, dof_id_type elem_id)
3580 {
3581 c0polyhedron_face_counts.push_back(cast_int<int>(elem.n_sides()));
3582
3583 for (auto s: elem.side_index_range())
3584 {
3585 connect.push_back(next_c0polyhedron_face_id++);
3586
3587 const std::vector<unsigned int> side_nodes = elem.nodes_on_side(s);
3588 c0polyhedron_face_node_counts.push_back(cast_int<int>(side_nodes.size()));
3589
3590 for (const auto elem_node_index : side_nodes)
3591 face_connect.push_back(
3592 get_exodus_node_id(elem, elem_id, elem_node_index));
3593 }
3594 };
3595
3596 const auto add_fixed_connectivity =
3597 [&](const Elem &elem, dof_id_type elem_id, std::size_t elem_index)
3598 {
3599 for (unsigned int j = 0;
3600 j < static_cast<unsigned int>(num_nodes_per_elem);
3601 ++j)
3602 {
3603 const auto connect_index =
3604 cast_int<unsigned int>((elem_index * num_nodes_per_elem) + j);
3605 const auto elem_node_index = conv.get_inverse_node_map(j);
3606 connect[connect_index] =
3607 get_exodus_node_id(elem, elem_id, elem_node_index);
3608 }
3609 };
3610
3611 for (auto i : index_range(element_id_vec))
3612 {
3613 unsigned int elem_id = element_id_vec[i];
3614 libmesh_elem_num_to_exodus[elem_id] = ++libmesh_elem_num_to_exodus_counter; // 1-based indexing for Exodus
3615
3616 const Elem & elem = mesh.elem_ref(elem_id);
3617
3618 // We *might* be able to get away with writing mixed element
3619 // types which happen to have the same number of nodes, but
3620 // do we actually *want* to get away with that?
3621 // .) No visualization software would be able to handle it.
3622 // .) There'd be no way for us to read it back in reliably.
3623 // .) Even elements with the same number of nodes may have different connectivities (?)
3624
3625 // This needs to be more than an assert so we don't fail
3626 // with a mysterious segfault while trying to write mixed
3627 // element meshes in optimized mode.
3628 libmesh_error_msg_if(elem.type() != conv.libmesh_elem_type(),
3629 "Error: Exodus requires all elements with a given subdomain ID to be the same type.\n"
3630 << "Can't write both "
3631 << Utility::enum_to_string(elem.type())
3632 << " and "
3633 << Utility::enum_to_string(conv.libmesh_elem_type())
3634 << " in the same block!");
3635
3636 if (is_c0polygon_block)
3637 add_c0polygon_connectivity(elem, elem_id);
3638 else if (is_c0polyhedron_block)
3639 add_c0polyhedron_connectivity(elem, elem_id);
3640 else
3641 add_fixed_connectivity(elem, elem_id, i);
3642
3643 // push_back() either elem_id+1 or the current Elem's
3644 // unique_id+1 into the elem_num_map, depending on the value
3645 // of the set_unique_ids_from_maps flag.
3646 if (this->set_unique_ids_from_maps)
3647 this->elem_num_map.push_back(elem.unique_id() + 1);
3648 else
3649 this->elem_num_map.push_back(elem_id + 1);
3650
3651 } // end for(i)
3652 }
3653 else // subdomain_id >= subdomain_id_end
3654 {
3655 // If this is a "fake" block of added sides, we build those as
3656 // we go.
3658
3659 libmesh_assert(num_elem_this_blk_it != num_elem_this_blk_vec.end());
3660 num_elem_this_blk = *num_elem_this_blk_it;
3661
3663
3664 std::size_t connect_index = 0;
3665 for (const auto & elem : mesh.active_element_ptr_range())
3666 {
3667 unsigned int local_node_index = elem->n_nodes();
3668
3669 for (auto s : elem->side_index_range())
3670 {
3672 continue;
3673
3674 if (elem->side_type(s) != elem_t)
3675 continue;
3676
3677 const std::vector<unsigned int> side_nodes =
3678 elem->nodes_on_side(s);
3679
3680 for (auto n : index_range(side_nodes))
3681 {
3682 libmesh_ignore(n);
3683 const int exodus_node_id = libmesh_map_find
3684 (discontinuous_node_indices,
3685 std::make_pair(elem->id(), local_node_index++));
3686 libmesh_assert_less(connect_index, connect.size());
3687 connect[connect_index++] = exodus_node_id;
3688 }
3689 }
3690 }
3691
3692 // Store num_elem_this_blk "fake" ids into the
3693 // elem_num_map. Use a traditional for-loop to avoid unused
3694 // variable warnings about the loop counter.
3695 for (int i=0; i<num_elem_this_blk; ++i)
3696 this->elem_num_map.push_back(next_fake_id++);
3697 }
3698
3699 ++num_elem_this_blk_it;
3700
3701 ex_err = exII::ex_put_conn
3702 (ex_id,
3703 exII::EX_ELEM_BLOCK,
3704 subdomain_id,
3705 is_c0polyhedron_block ? nullptr : connect.data(), // node_conn
3706 nullptr, // elem_edge_conn (unused)
3707 is_c0polyhedron_block ? connect.data() : nullptr);
3708 EX_CHECK_ERR(ex_err, "Error writing element connectivities");
3709
3710 if (is_c0polygon_block)
3711 {
3712 ex_err = exII::ex_put_entity_count_per_polyhedra
3713 (ex_id,
3714 exII::EX_ELEM_BLOCK,
3715 subdomain_id,
3716 c0polygon_node_counts.data());
3717 EX_CHECK_ERR(ex_err, "Error writing polygon node counts");
3718 }
3719 if (is_c0polyhedron_block)
3720 {
3721 ex_err = exII::ex_put_entity_count_per_polyhedra
3722 (ex_id,
3723 exII::EX_ELEM_BLOCK,
3724 subdomain_id,
3725 c0polyhedron_face_counts.data());
3726 EX_CHECK_ERR(ex_err, "Error writing polyhedron face counts");
3727 }
3728 } // end for (auto & [subdomain_id, element_id_vec] : subdomain_map)
3729
3730 if (has_c0polyhedron_blocks)
3731 {
3732 libmesh_assert_equal_to(c0polyhedron_face_node_counts.size(),
3733 cast_int<std::size_t>(num_face));
3734 libmesh_assert_equal_to(next_c0polyhedron_face_id, num_face + 1);
3735
3736 ex_err = exII::ex_put_conn
3737 (ex_id,
3738 exII::EX_FACE_BLOCK,
3739 c0polyhedron_face_block_id,
3740 face_connect.data(), // node_conn
3741 nullptr, // elem_edge_conn (unused)
3742 nullptr); // elem_face_conn (unused)
3743 EX_CHECK_ERR(ex_err, "Error writing polyhedron face connectivities");
3744
3745 ex_err = exII::ex_put_entity_count_per_polyhedra
3746 (ex_id,
3747 exII::EX_FACE_BLOCK,
3748 c0polyhedron_face_block_id,
3749 c0polyhedron_face_node_counts.data());
3750 EX_CHECK_ERR(ex_err, "Error writing polyhedron face node counts");
3751 }
3752
3753 // write out the element number map that we created
3754 ex_err = exII::ex_put_elem_num_map(ex_id, elem_num_map.data());
3755 EX_CHECK_ERR(ex_err, "Error writing element map");
3756
3757 // Write out the block names
3758 if (num_elem_blk > 0)
3759 {
3760 ex_err = exII::ex_put_names(ex_id, exII::EX_ELEM_BLOCK, names_table.get_char_star_star());
3761 EX_CHECK_ERR(ex_err, "Error writing element block names");
3762 }
3763
3764 if (num_face_blk > 0)
3765 {
3766 ex_err = exII::ex_put_names
3767 (ex_id,
3768 exII::EX_FACE_BLOCK,
3769 face_block_names_table.get_char_star_star());
3770 EX_CHECK_ERR(ex_err, "Error writing face block names");
3771 }
3772
3773 // Write out edge blocks if we have any
3774 for (const auto & pr : edge_id_to_conn)
3775 {
3776 ex_err = exII::ex_put_conn
3777 (ex_id,
3778 exII::EX_EDGE_BLOCK,
3779 pr.first,
3780 pr.second.data(), // node_conn
3781 nullptr, // elem_edge_conn (unused)
3782 nullptr); // elem_face_conn (unused)
3783 EX_CHECK_ERR(ex_err, "Error writing element connectivities");
3784 }
3785
3786 // Write out the edge block names, if any.
3787 if (num_edge_blk > 0)
3788 {
3789 ex_err = exII::ex_put_names
3790 (ex_id,
3791 exII::EX_EDGE_BLOCK,
3792 edge_block_names_table.get_char_star_star());
3793 EX_CHECK_ERR(ex_err, "Error writing edge block names");
3794 }
3795}
const std::string & get_edgeset_name(boundary_id_type id) const
std::vector< BCTuple > build_edge_list() const
Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.
unique_id_type unique_id() const
Definition dof_object.h:849
dof_id_type id() const
Definition dof_object.h:833
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual unsigned int n_nodes() const =0
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const =0
Similar to Elem::local_side_node(), but instead of a side id, takes an edge id and a node id on that ...
subdomain_id_type subdomain_id() const
Definition elem.h:2712
static constexpr unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition elem.h:664
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i)=0
virtual ElemType side_type(const unsigned int s) const =0
virtual unsigned int n_sides() const =0
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2605
std::map< dof_id_type, dof_id_type > libmesh_elem_num_to_exodus
std::map< dof_id_type, dof_id_type > libmesh_node_num_to_exodus
virtual dof_id_type max_elem_id() const =0
std::string & subdomain_name(subdomain_id_type id)
Definition mesh_base.C:1902
virtual const Elem & elem_ref(const dof_id_type i) const
Definition mesh_base.h:785
std::string enum_to_string(const T e)
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303

References _add_sides, _max_name_length, _run_only_on_proc0, block_ids, libMesh::BoundaryInfo::build_edge_list(), libMesh::Elem::build_edge_ptr(), libMesh::C0POLYGON, libMesh::C0POLYHEDRON, connect, elem_num_map, libMesh::MeshBase::elem_ptr(), libMesh::MeshBase::elem_ref(), libMesh::Utility::enum_to_string(), ex_err, ex_id, libMesh::MeshBase::get_boundary_info(), libMesh::ExodusII_IO_Helper::NamesData::get_char_star(), libMesh::ExodusII_IO_Helper::NamesData::get_char_star_star(), get_conversion(), libMesh::BoundaryInfo::get_edgeset_name(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::invalid_uint, libMesh::libmesh_assert(), libmesh_elem_num_to_exodus, libMesh::libmesh_ignore(), libmesh_node_num_to_exodus, libMesh::Elem::local_edge_node(), libMesh::MeshBase::max_elem_id(), libMesh::MeshBase::max_node_id(), mesh, libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::MeshBase::next_unique_id(), libMesh::Elem::node_id(), libMesh::Elem::node_index_range(), libMesh::Elem::nodes_on_side(), num_edge_blk, num_elem, num_elem_blk, num_elem_this_blk, num_face, num_face_blk, num_nodes_per_elem, libMesh::out, libMesh::ParallelObject::processor_id(), libMesh::ExodusII_IO_Helper::NamesData::push_back_entry(), libMesh::EquationSystems::redundant_added_side(), set_unique_ids_from_maps, libMesh::Elem::side_index_range(), libMesh::Elem::side_type(), libMesh::Elem::subdomain_id(), libMesh::MeshBase::subdomain_name(), libMesh::Elem::type(), libMesh::Elem::type_to_n_nodes_map, and libMesh::DofObject::unique_id().

Referenced by ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl().

◆ write_elemset_data()

void libMesh::ExodusII_IO_Helper::write_elemset_data ( int  timestep,
const std::vector< std::string > &  var_names,
const std::vector< std::set< elemset_id_type > > &  elemset_ids_in,
const std::vector< std::map< std::pair< dof_id_type, elemset_id_type >, Real > > &  elemset_vals 
)

Write elemset data for the requested timestep.

Definition at line 4705 of file exodusII_io_helper.C.

4710{
4711 LOG_SCOPE("write_elemset_data()", "ExodusII_IO_Helper");
4712
4713 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4714 return;
4715
4716 // Write the elemset variable names to file. This function should
4717 // only be called once for ELEMSET variables, repeated calls to
4718 // write_var_names() overwrites/changes the order of names that were
4719 // there previously, and will mess up any data that has already been
4720 // written.
4721 this->write_var_names(ELEMSET, var_names);
4722
4723 // We now call the API to read the elemset info even though we are
4724 // in the middle of writing. This is a bit counter-intuitive, but it
4725 // seems to work provided that you have already written the mesh
4726 // itself... read_elemset_info() fills in the following data
4727 // members:
4728 // .) id_to_elemset_names
4729 // .) num_elems_per_set
4730 // .) num_elem_df_per_set
4731 // .) elemset_list
4732 // .) elemset_id_list
4733 // .) id_to_elemset_names
4734 this->read_elemset_info();
4735
4736 // The "truth" table for elemset variables. elemset_var_tab is a
4737 // logically (num_elem_sets x num_elemset_vars) integer array of 0s and
4738 // 1s indicating which elemsets a given elemset variable is defined
4739 // on.
4740 std::vector<int> elemset_var_tab(num_elem_sets * var_names.size());
4741
4742 int offset=0;
4743 for (int es=0; es<num_elem_sets; ++es)
4744 {
4745 // Debugging
4746 // libMesh::out << "Writing elemset variable values for elemset "
4747 // << es << ", elemset_id = " << elemset_ids[es]
4748 // << std::endl;
4749
4750 // We know num_elems_per_set because we called read_elemset_info() above.
4751 offset += (es > 0 ? num_elems_per_set[es-1] : 0);
4752 this->read_elemset(es, offset);
4753
4754 // For each variable in var_names, write the values for the
4755 // current elemset, if any.
4756 for (auto var : index_range(var_names))
4757 {
4758 // Debugging
4759 // libMesh::out << "Writing elemset variable values for var " << var << std::endl;
4760
4761 // If this var has no values on this elemset, go to the next one.
4762 if (!elemset_ids_in[var].count(elemset_ids[es]))
4763 continue;
4764
4765 // Otherwise, fill in this entry of the nodeset truth table.
4766 elemset_var_tab[es*var_names.size() + var] = 1;
4767
4768 // Data vector that will eventually be passed to exII::ex_put_var().
4769 std::vector<Real> elemset_var_vals(num_elems_per_set[es]);
4770
4771 // Get reference to the (elem_id, elemset_id) -> Real map for this variable.
4772 const auto & data_map = elemset_vals[var];
4773
4774 // Loop over entries in current elemset.
4775 for (int i=0; i<num_elems_per_set[es]; ++i)
4776 {
4777 // Here we convert Exodus elem ids to libMesh node ids
4778 // simply by subtracting 1. We should probably use the
4779 // exodus_elem_num_to_libmesh data structure for this,
4780 // but I don't think it is set up at the time when this
4781 // function is normally called.
4782 dof_id_type libmesh_elem_id = elemset_list[i + offset] - 1;
4783
4784 // Construct a key to look up values in data_map.
4785 std::pair<dof_id_type, elemset_id_type> key =
4786 std::make_pair(libmesh_elem_id, elemset_ids[es]);
4787
4788 // Debugging:
4789 // libMesh::out << "Searching for key = (" << key.first << ", " << key.second << ")" << std::endl;
4790
4791 // We require that the user provided either no values for
4792 // this (var, elemset) combination (in which case we don't
4793 // reach this point) or a value for _every_ elem in this
4794 // elemset for this var, so we use the libmesh_map_find()
4795 // macro to check for this.
4796 elemset_var_vals[i] = libmesh_map_find(data_map, key);
4797 } // end for (node in nodeset[ns])
4798
4799 // Write elemset values to Exodus file
4800 if (elemset_var_vals.size() > 0)
4801 {
4802 ex_err = exII::ex_put_var
4803 (ex_id,
4804 timestep,
4805 exII::EX_ELEM_SET,
4806 var + 1, // 1-based variable index of current variable
4807 elemset_ids[es],
4809 MappedOutputVector(elemset_var_vals, _single_precision).data());
4810 EX_CHECK_ERR(ex_err, "Error writing elemset vars.");
4811 }
4812 } // end for (var in var_names)
4813 } // end for (ns)
4814
4815 // Finally, write the elemset truth table to file.
4816 ex_err =
4817 exII::ex_put_truth_table(ex_id,
4818 exII::EX_ELEM_SET, // exII::ex_entity_type
4820 cast_int<int>(var_names.size()),
4821 elemset_var_tab.data());
4822 EX_CHECK_ERR(ex_err, "Error writing elemset var truth table.");
4823}
void read_elemset_info()
Reads information about all of the elemsets in the ExodusII mesh file.
void read_elemset(int id, int offset)
Reads information about elemset id and inserts it into the global elemset array at the position offse...

References _run_only_on_proc0, _single_precision, ELEMSET, elemset_ids, elemset_list, ex_err, ex_id, libMesh::index_range(), num_elem_sets, num_elems_per_set, libMesh::ParallelObject::processor_id(), read_elemset(), read_elemset_info(), and write_var_names().

◆ write_elemsets()

void libMesh::ExodusII_IO_Helper::write_elemsets ( const MeshBase &  mesh)

Write elemsets stored on the Mesh to the exo file.

Definition at line 4212 of file exodusII_io_helper.C.

4213{
4214 LOG_SCOPE("write_elemsets()", "ExodusII_IO_Helper");
4215
4216 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4217 return;
4218
4219 // TODO: Add support for named elemsets
4220 // NamesData names_table(elemsets.size(), _max_name_length);
4221
4222 // We only need to write elemsets if the Mesh has an extra elem
4223 // integer called "elemset_code" defined on it.
4224 if (mesh.has_elem_integer("elemset_code"))
4225 {
4226 std::map<elemset_id_type, std::vector<int>> exodus_elemsets;
4227
4228 unsigned int elemset_index =
4229 mesh.get_elem_integer_index("elemset_code");
4230
4231 // Catch ids returned from MeshBase::get_elemsets() calls
4232 MeshBase::elemset_type set_ids;
4233 for (const auto & elem : mesh.element_ptr_range())
4234 {
4235 dof_id_type elemset_code =
4236 elem->get_extra_integer(elemset_index);
4237
4238 // Look up which element set ids (if any) this elemset_code corresponds to.
4239 mesh.get_elemsets(elemset_code, set_ids);
4240
4241 // Debugging
4242 // libMesh::out << "elemset_code = " << elemset_code << std::endl;
4243 // for (const auto & set_id : set_ids)
4244 // libMesh::out << set_id << " ";
4245 // libMesh::out << std::endl;
4246
4247 // Store this Elem id in every set to which it belongs.
4248 for (const auto & set_id : set_ids)
4249 exodus_elemsets[set_id].push_back(libmesh_elem_num_to_exodus[elem->id()]);
4250 }
4251
4252 // Debugging: print contents of exodus_elemsets map
4253 // for (const auto & [set_id, elem_ids] : exodus_elemsets)
4254 // {
4255 // libMesh::out << "elemset " << set_id << ": ";
4256 // for (const auto & elem_id : elem_ids)
4257 // libMesh::out << elem_id << " ";
4258 // libMesh::out << std::endl;
4259 // }
4260
4261 // Only continue if we actually had some elements in sets
4262 if (!exodus_elemsets.empty())
4263 {
4264 // Reserve space, loop over newly-created map, construct
4265 // exII::ex_set objects to be passed to exII::ex_put_sets(). Note:
4266 // we do non-const iteration since Exodus requires non-const pointers
4267 // to be passed to its APIs.
4268 std::vector<exII::ex_set> sets;
4269 sets.reserve(exodus_elemsets.size());
4270
4271 for (auto & [elem_set_id, ids_vec] : exodus_elemsets)
4272 {
4273 // TODO: Add support for named elemsets
4274 // names_table.push_back_entry(mesh.get_elemset_name(elem_set_id));
4275
4276 exII::ex_set & current_set = sets.emplace_back();
4277 current_set.id = elem_set_id;
4278 current_set.type = exII::EX_ELEM_SET;
4279 current_set.num_entry = ids_vec.size();
4280 current_set.num_distribution_factor = 0;
4281 current_set.entry_list = ids_vec.data();
4282 current_set.extra_list = nullptr; // extra_list is used for sidesets, not needed for elemsets
4283 current_set.distribution_factor_list = nullptr; // not used for elemsets
4284 }
4285
4286 // Sanity check: make sure the number of elemsets we already wrote to the header
4287 // matches the number of elemsets we just constructed by looping over the Mesh.
4288 libmesh_assert_msg(num_elem_sets == cast_int<int>(exodus_elemsets.size()),
4289 "Mesh has " << exodus_elemsets.size()
4290 << " elemsets, but header was written with num_elem_sets == " << num_elem_sets);
4291 libmesh_assert_msg(num_elem_sets == cast_int<int>(mesh.n_elemsets()),
4292 "mesh.n_elemsets() == " << mesh.n_elemsets()
4293 << ", but header was written with num_elem_sets == " << num_elem_sets);
4294
4295 ex_err = exII::ex_put_sets(ex_id, exodus_elemsets.size(), sets.data());
4296 EX_CHECK_ERR(ex_err, "Error writing elemsets");
4297
4298 // TODO: Add support for named elemsets
4299 // ex_err = exII::ex_put_names(ex_id, exII::EX_ELEM_SET, names_table.get_char_star_star());
4300 // EX_CHECK_ERR(ex_err, "Error writing elemset names");
4301 } // end if (!exodus_elemsets.empty())
4302 } // end if (mesh.has_elem_integer("elemset_code"))
4303}
unsigned int get_elem_integer_index(std::string_view name) const
Definition mesh_base.C:689
void get_elemsets(dof_id_type elemset_code, MeshBase::elemset_type &id_set_to_fill) const
Look up the element sets for a given elemset code and vice-versa.
Definition mesh_base.C:492
std::set< elemset_id_type > elemset_type
Typedef for the "set" container used to store elemset ids.
Definition mesh_base.h:463

References _run_only_on_proc0, ex_err, ex_id, libMesh::MeshBase::get_elem_integer_index(), libMesh::MeshBase::get_elemsets(), libMesh::DofObject::get_extra_integer(), libMesh::MeshBase::has_elem_integer(), libMesh::DofObject::id(), libmesh_elem_num_to_exodus, mesh, libMesh::MeshBase::n_elemsets(), num_elem_sets, and libMesh::ParallelObject::processor_id().

◆ write_global_values()

void libMesh::ExodusII_IO_Helper::write_global_values ( const std::vector< Real > &  values,
int  timestep 
)

Writes the vector of global variables.

Definition at line 5413 of file exodusII_io_helper.C.

5414{
5415 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5416 return;
5417
5418 if (!values.empty())
5419 {
5420 ex_err = exII::ex_put_var
5421 (ex_id,
5422 timestep,
5423 exII::EX_GLOBAL,
5424 1, // var index
5425 0, // obj_id (not used)
5427 MappedOutputVector(values, _single_precision).data());
5428
5429 EX_CHECK_ERR(ex_err, "Error writing global values.");
5430
5431 this->update();
5432 }
5433}

References _run_only_on_proc0, _single_precision, ex_err, ex_id, num_global_vars, libMesh::ParallelObject::processor_id(), and update().

◆ write_information_records()

void libMesh::ExodusII_IO_Helper::write_information_records ( const std::vector< std::string > &  records)

Writes the vector of information records.

Definition at line 5375 of file exodusII_io_helper.C.

5376{
5377 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5378 return;
5379
5380 // There may already be information records in the file (for
5381 // example, if we're appending) and in that case, according to the
5382 // Exodus documentation, writing more information records is not
5383 // supported.
5384 int num_info = inquire(*this, exII::EX_INQ_INFO, "Error retrieving the number of information records from file!");
5385 if (num_info > 0)
5386 {
5387 libMesh::err << "Warning! The Exodus file already contains information records.\n"
5388 << "Exodus does not support writing additional records in this situation."
5389 << std::endl;
5390 return;
5391 }
5392
5393 int num_records = cast_int<int>(records.size());
5394
5395 if (num_records > 0)
5396 {
5397 NamesData info(num_records, MAX_LINE_LENGTH);
5398
5399 // If an entry is longer than MAX_LINE_LENGTH characters it's not an error, we just
5400 // write the first MAX_LINE_LENGTH characters to the file.
5401 for (const auto & record : records)
5402 info.push_back_entry(record);
5403
5404 ex_err = exII::ex_put_info(ex_id, num_records, info.get_char_star_star());
5405 EX_CHECK_ERR(ex_err, "Error writing global values.");
5406
5407 this->update();
5408 }
5409}
MPI_Info info

References _run_only_on_proc0, libMesh::err, ex_err, ex_id, libMesh::ParallelObject::processor_id(), and update().

◆ write_nodal_coordinates()

void libMesh::ExodusII_IO_Helper::write_nodal_coordinates ( const MeshBase &  mesh,
bool  use_discontinuous = false 
)
virtual

Writes the nodal coordinates contained in "mesh".

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 2889 of file exodusII_io_helper.C.

2890{
2891 if ((_run_only_on_proc0) && (this->processor_id() != 0))
2892 return;
2893
2894 // Clear existing data from any previous calls.
2895 x.clear();
2896 y.clear();
2897 z.clear();
2898 node_num_map.clear();
2899
2900 // Reserve space in the nodal coordinate vectors. num_nodes is
2901 // exact, this just allows us to do away with one potentially
2902 // error-inducing loop index.
2903 x.reserve(num_nodes);
2904 y.reserve(num_nodes);
2905 z.reserve(num_nodes);
2906
2907 auto push_node = [this](const Point & p) {
2908 x.push_back(p(0) + _coordinate_offset(0));
2909
2910#if LIBMESH_DIM > 1
2911 y.push_back(p(1) + _coordinate_offset(1));
2912#else
2913 y.push_back(0.);
2914#endif
2915#if LIBMESH_DIM > 2
2916 z.push_back(p(2) + _coordinate_offset(2));
2917#else
2918 z.push_back(0.);
2919#endif
2920 };
2921
2922 // And in the node_num_map. If the user has set the
2923 // _set_unique_ids_from_maps flag, then we will write the Node
2924 // unique_ids to the node_num_map, otherwise we will just write a
2925 // trivial node_num_map, since in that we don't write the unique_id
2926 // information to the Exodus file. In other words, set the
2927 // _set_unique_ids_from_maps flag to true on both the reading and
2928 // writing ExodusII_IO objects if you want to preserve the
2929 // node_num_map information without actually renumbering the Nodes
2930 // in libmesh according to the node_num_map.
2931 //
2932 // One reason why you might not want to actually renumber the Nodes
2933 // in libmesh according to the node_num_map is that it can introduce
2934 // undesirable large "gaps" in the numbering, e.g. Nodes numbered
2935 // [0, 1, 1000, 10001] which is not ideal for the ReplicatedMesh
2936 // _nodes data structure, which stores the Nodes in a contiguous
2937 // array based on Node id.
2938
2939 // Let's skip the node_num_map in the discontinuous and add_sides
2940 // cases, since we're effectively duplicating nodes for the sake of
2941 // discontinuous visualization, so it isn't clear how to deal with
2942 // node_num_map here. This means that writing meshes in such a way
2943 // won't work with element numberings that have id "holes".
2944
2945 if (!use_discontinuous && !_add_sides)
2946 node_num_map.reserve(num_nodes);
2947
2948 // Clear out any previously-mapped node IDs.
2950
2951 if (!use_discontinuous)
2952 {
2953 for (const auto & node_ptr : mesh.node_ptr_range())
2954 {
2955 const Node & node = *node_ptr;
2956
2957 push_node(node);
2958
2959 // Fill in node_num_map entry with the proper (1-based) node
2960 // id, unless we're not going to be able to keep the map up
2961 // later. If the user has chosen to _set_unique_ids_from_maps,
2962 // then we fill up the node_num_map with (1-based) unique
2963 // ids rather than node ids.
2964 if (!_add_sides)
2965 {
2966 if (this->set_unique_ids_from_maps)
2967 node_num_map.push_back(node.unique_id() + 1);
2968 else
2969 node_num_map.push_back(node.id() + 1);
2970 }
2971
2972 // Also map the zero-based libmesh node id to the (1-based)
2973 // index in the node_num_map it corresponds to
2974 // (this is equivalent to the current size of the "x" vector,
2975 // so we just use x.size()). This map is used to look up
2976 // an Exodus Node id given a libMesh Node id, so it does
2977 // involve unique_ids.
2978 libmesh_node_num_to_exodus[ cast_int<int>(node.id()) ] = cast_int<int>(x.size());
2979 } // end for (node_ptr)
2980 }
2981 else // use_discontinuous
2982 {
2983 for (const auto & elem : mesh.active_element_ptr_range())
2984 for (const Node & node : elem->node_ref_range())
2985 {
2986 push_node(node);
2987
2988 // Let's skip the node_num_map in the discontinuous
2989 // case, since we're effectively duplicating nodes for
2990 // the sake of discontinuous visualization, so it isn't
2991 // clear how to deal with node_num_map here. This means
2992 // that writing discontinuous meshes won't work with
2993 // element numberings that have "holes".
2994 }
2995 }
2996
2997 if (_add_sides)
2998 {
2999 // To match the numbering of parallel-generated nodal solutions
3000 // on fake side nodes, we need to loop through elements from
3001 // earlier ranks first.
3002 std::vector<std::vector<const Elem *>>
3003 elems_by_pid(mesh.n_processors());
3004
3005 for (const auto & elem : mesh.active_element_ptr_range())
3006 elems_by_pid[elem->processor_id()].push_back(elem);
3007
3008 for (auto p : index_range(elems_by_pid))
3009 for (const Elem * elem : elems_by_pid[p])
3010 for (auto s : elem->side_index_range())
3011 {
3013 continue;
3014
3015 const std::vector<unsigned int> side_nodes =
3016 elem->nodes_on_side(s);
3017
3018 for (auto n : side_nodes)
3019 push_node(elem->point(n));
3020 }
3021
3022 // Node num maps just don't make sense if we're adding a bunch
3023 // of visualization nodes that are independent copies of the
3024 // same libMesh node.
3025 node_num_map.clear();
3026 }
3027
3028 ex_err = exII::ex_put_coord
3029 (ex_id,
3030 x.empty() ? nullptr : MappedOutputVector(x, _single_precision).data(),
3031 y.empty() ? nullptr : MappedOutputVector(y, _single_precision).data(),
3032 z.empty() ? nullptr : MappedOutputVector(z, _single_precision).data());
3033
3034 EX_CHECK_ERR(ex_err, "Error writing coordinates to Exodus file.");
3035
3036 if (!use_discontinuous && !_add_sides)
3037 {
3038 // Also write the (1-based) node_num_map to the file.
3039 ex_err = exII::ex_put_node_num_map(ex_id, node_num_map.data());
3040 EX_CHECK_ERR(ex_err, "Error writing node_num_map");
3041 }
3042}
A Node is like a Point, but with more information.
Definition node.h:55
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:41

References _add_sides, _coordinate_offset, _run_only_on_proc0, _single_precision, libMesh::ExodusII_IO_Helper::MappedOutputVector::data(), ex_err, ex_id, libMesh::DofObject::id(), libMesh::index_range(), libmesh_node_num_to_exodus, mesh, libMesh::ParallelObject::n_processors(), node_num_map, libMesh::Elem::node_ref_range(), libMesh::Elem::nodes_on_side(), num_nodes, libMesh::Elem::point(), libMesh::DofObject::processor_id(), libMesh::ParallelObject::processor_id(), libMesh::EquationSystems::redundant_added_side(), set_unique_ids_from_maps, libMesh::Elem::side_index_range(), libMesh::DofObject::unique_id(), x, y, and z.

Referenced by ExodusC0PolyhedronTest::test_write_and_read_mixed_hex_tet_block_names_impl().

◆ write_nodal_values()

void libMesh::ExodusII_IO_Helper::write_nodal_values ( int  var_id,
const std::vector< Real > &  values,
int  timestep 
)

Writes the vector of values to a nodal variable.

Definition at line 5347 of file exodusII_io_helper.C.

5350{
5351 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5352 return;
5353
5354 if (!values.empty())
5355 {
5356 libmesh_assert_equal_to(values.size(), std::size_t(num_nodes));
5357
5358 ex_err = exII::ex_put_var
5359 (ex_id,
5360 timestep,
5361 exII::EX_NODAL,
5362 var_id,
5363 1, // exII::ex_entity_id, not sure exactly what this is but in the ex_put_nodal_var.c shim, they pass 1
5364 num_nodes,
5365 MappedOutputVector(values, _single_precision).data());
5366
5367 EX_CHECK_ERR(ex_err, "Error writing nodal values.");
5368
5369 this->update();
5370 }
5371}

References _run_only_on_proc0, _single_precision, ex_err, ex_id, num_nodes, libMesh::ParallelObject::processor_id(), and update().

Referenced by libMesh::Nemesis_IO_Helper::write_nodal_solution(), libMesh::Nemesis_IO_Helper::write_nodal_solution(), and libMesh::Nemesis_IO_Helper::write_nodal_solution().

◆ write_nodeset_data()

void libMesh::ExodusII_IO_Helper::write_nodeset_data ( int  timestep,
const std::vector< std::string > &  var_names,
const std::vector< std::set< boundary_id_type > > &  node_boundary_ids,
const std::vector< std::map< BoundaryInfo::NodeBCTuple, Real > > &  bc_vals 
)

Write nodeset data for the requested timestep.

Definition at line 4600 of file exodusII_io_helper.C.

4605{
4606 LOG_SCOPE("write_nodeset_data()", "ExodusII_IO_Helper");
4607
4608 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4609 return;
4610
4611 // Write the nodeset variable names to file. This function should
4612 // only be called once for NODESET variables, repeated calls to
4613 // write_var_names() overwrites/changes the order of names that were
4614 // there previously, and will mess up any data that has already been
4615 // written.
4616 this->write_var_names(NODESET, var_names);
4617
4618 // For all nodesets, reads and fills in the arrays:
4619 // nodeset_ids
4620 // num_nodes_per_set
4621 // node_sets_node_index - starting index for each nodeset in the node_sets_node_list vector
4622 // node_sets_node_list
4623 // Note: we need these arrays so that we know what data to write
4624 this->read_all_nodesets();
4625
4626 // The "truth" table for nodeset variables. nset_var_tab is a
4627 // logically (num_node_sets x num_nset_var) integer array of 0s and
4628 // 1s indicating which nodesets a given nodeset variable is defined
4629 // on.
4630 std::vector<int> nset_var_tab(num_node_sets * var_names.size());
4631
4632 for (int ns=0; ns<num_node_sets; ++ns)
4633 {
4634 // The offset into the node_sets_node_list for the current nodeset
4635 int offset = node_sets_node_index[ns];
4636
4637 // For each variable in var_names, write the values for the
4638 // current nodeset, if any.
4639 for (auto var : index_range(var_names))
4640 {
4641 // If this var has no values on this nodeset, go to the next one.
4642 if (!node_boundary_ids[var].count(nodeset_ids[ns]))
4643 continue;
4644
4645 // Otherwise, fill in this entry of the nodeset truth table.
4646 nset_var_tab[ns*var_names.size() + var] = 1;
4647
4648 // Data vector that will eventually be passed to exII::ex_put_var().
4649 std::vector<Real> nset_var_vals(num_nodes_per_set[ns]);
4650
4651 // Get reference to the NodeBCTuple -> Real map for this variable.
4652 const auto & data_map = bc_vals[var];
4653
4654 // Loop over entries in current nodeset.
4655 for (int i=0; i<num_nodes_per_set[ns]; ++i)
4656 {
4657 // Here we convert Exodus node ids to libMesh node ids by
4658 // subtracting 1. We should probably use the
4659 // exodus_node_num_to_libmesh data structure for this, but
4660 // I don't think it is set up at the time when
4661 // write_nodeset_data() would normally be called.
4662 dof_id_type libmesh_node_id = node_sets_node_list[i + offset] - 1;
4663
4664 // Construct a key to look up values in data_map.
4666 std::make_tuple(libmesh_node_id, nodeset_ids[ns]);
4667
4668 // We require that the user provided either no values for
4669 // this (var, nodeset) combination (in which case we don't
4670 // reach this point) or a value for _every_ node in this
4671 // nodeset for this var, so we use the libmesh_map_find()
4672 // macro to check for this.
4673 nset_var_vals[i] = libmesh_map_find(data_map, key);
4674 } // end for (node in nodeset[ns])
4675
4676 // Write nodeset values to Exodus file
4677 if (nset_var_vals.size() > 0)
4678 {
4679 ex_err = exII::ex_put_var
4680 (ex_id,
4681 timestep,
4682 exII::EX_NODE_SET,
4683 var + 1, // 1-based variable index of current variable
4684 nodeset_ids[ns],
4686 MappedOutputVector(nset_var_vals, _single_precision).data());
4687 EX_CHECK_ERR(ex_err, "Error writing nodeset vars.");
4688 }
4689 } // end for (var in var_names)
4690 } // end for (ns)
4691
4692 // Finally, write the nodeset truth table.
4693 ex_err =
4694 exII::ex_put_truth_table(ex_id,
4695 exII::EX_NODE_SET,
4697 cast_int<int>(var_names.size()),
4698 nset_var_tab.data());
4699 EX_CHECK_ERR(ex_err, "Error writing nodeset var truth table.");
4700}
void read_all_nodesets()
New API that reads all nodesets simultaneously.

References _run_only_on_proc0, _single_precision, ex_err, ex_id, libMesh::index_range(), node_sets_node_index, node_sets_node_list, NODESET, nodeset_ids, num_node_sets, num_nodes_per_set, libMesh::ParallelObject::processor_id(), read_all_nodesets(), and write_var_names().

◆ write_nodesets()

void libMesh::ExodusII_IO_Helper::write_nodesets ( const MeshBase &  mesh)
virtual

Writes the nodesets contained in "mesh".

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 3924 of file exodusII_io_helper.C.

3925{
3926 LOG_SCOPE("write_nodesets()", "ExodusII_IO_Helper");
3927
3928 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3929 return;
3930
3931 // build_node_list() builds a sorted list of (node-id, bc-id) tuples
3932 // that is sorted by node-id, but we actually want it to be sorted
3933 // by bc-id, i.e. the second argument of the tuple.
3934 auto bc_tuples =
3936
3937 // We use std::stable_sort() here so that the entries within a
3938 // single nodeset remain sorted in node-id order, but now the
3939 // smallest boundary id's nodes appear first in the list, followed
3940 // by the second smallest, etc. That is, we are purposely doing two
3941 // different sorts here, with the first one being within the
3942 // build_node_list() call itself.
3943 std::stable_sort(bc_tuples.begin(), bc_tuples.end(),
3944 [](const BoundaryInfo::NodeBCTuple & t1,
3945 const BoundaryInfo::NodeBCTuple & t2)
3946 { return std::get<1>(t1) < std::get<1>(t2); });
3947
3948 std::vector<boundary_id_type> node_boundary_ids;
3949 mesh.get_boundary_info().build_node_boundary_ids(node_boundary_ids);
3950
3951 // Add any empty-but-named node boundary ids
3952 for (const auto & pair : mesh.get_boundary_info().get_nodeset_name_map())
3953 {
3954 const boundary_id_type id = pair.first;
3955
3956 if (std::find(node_boundary_ids.begin(),
3957 node_boundary_ids.end(), id)
3958 == node_boundary_ids.end())
3959 node_boundary_ids.push_back(id);
3960 }
3961
3962 // Write out the nodeset names, but only if there is something to write
3963 if (node_boundary_ids.size() > 0)
3964 {
3965 NamesData names_table(node_boundary_ids.size(), _max_name_length);
3966
3967 // Vectors to be filled and passed to exII::ex_put_concat_sets()
3968 // Use existing class members and avoid variable shadowing.
3969 nodeset_ids.clear();
3970 num_nodes_per_set.clear();
3971 num_node_df_per_set.clear();
3972 node_sets_node_index.clear();
3973 node_sets_node_list.clear();
3974
3975 // Pre-allocate space
3976 nodeset_ids.reserve(node_boundary_ids.size());
3977 num_nodes_per_set.reserve(node_boundary_ids.size());
3978 num_node_df_per_set.resize(node_boundary_ids.size()); // all zeros
3979 node_sets_node_index.reserve(node_boundary_ids.size());
3980 node_sets_node_list.reserve(bc_tuples.size());
3981
3982 // Assign entries to node_sets_node_list, keeping track of counts as we go.
3983 std::map<boundary_id_type, unsigned int> nodeset_counts;
3984 for (auto id : node_boundary_ids)
3985 nodeset_counts[id] = 0;
3986
3987 for (const auto & t : bc_tuples)
3988 {
3989 const dof_id_type & node_id = std::get<0>(t) + 1; // Note: we use 1-based node ids in Exodus!
3990 const boundary_id_type & nodeset_id = std::get<1>(t);
3991 node_sets_node_list.push_back(node_id);
3992 nodeset_counts[nodeset_id] += 1;
3993 }
3994
3995 // Fill in other indexing vectors needed by Exodus
3996 unsigned int running_sum = 0;
3997 for (const auto & pr : nodeset_counts)
3998 {
3999 nodeset_ids.push_back(pr.first);
4000 num_nodes_per_set.push_back(pr.second);
4001 node_sets_node_index.push_back(running_sum);
4002 names_table.push_back_entry(mesh.get_boundary_info().get_nodeset_name(pr.first));
4003 running_sum += pr.second;
4004 }
4005
4006 // Fill in an exII::ex_set_specs object which can then be passed to
4007 // the ex_put_concat_sets() function.
4008 exII::ex_set_specs set_data = {};
4009 set_data.sets_ids = nodeset_ids.data();
4010 set_data.num_entries_per_set = num_nodes_per_set.data();
4011 set_data.num_dist_per_set = num_node_df_per_set.data(); // zeros
4012 set_data.sets_entry_index = node_sets_node_index.data();
4013 set_data.sets_dist_index = node_sets_node_index.data(); // dummy value
4014 set_data.sets_entry_list = node_sets_node_list.data();
4015
4016 // Write all nodesets together.
4017 ex_err = exII::ex_put_concat_sets(ex_id, exII::EX_NODE_SET, &set_data);
4018 EX_CHECK_ERR(ex_err, "Error writing concatenated nodesets");
4019
4020 // Write out the nodeset names
4021 ex_err = exII::ex_put_names(ex_id, exII::EX_NODE_SET, names_table.get_char_star_star());
4022 EX_CHECK_ERR(ex_err, "Error writing nodeset names");
4023 }
4024}
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
const std::string & get_nodeset_name(boundary_id_type id) const

References _max_name_length, _run_only_on_proc0, libMesh::BoundaryInfo::build_node_boundary_ids(), libMesh::BoundaryInfo::build_node_list(), ex_err, ex_id, libMesh::MeshBase::get_boundary_info(), libMesh::ExodusII_IO_Helper::NamesData::get_char_star_star(), libMesh::BoundaryInfo::get_nodeset_name(), libMesh::BoundaryInfo::get_nodeset_name_map(), mesh, node_sets_node_index, node_sets_node_list, nodeset_ids, num_node_df_per_set, num_nodes_per_set, libMesh::ParallelObject::processor_id(), and libMesh::ExodusII_IO_Helper::NamesData::push_back_entry().

◆ write_sideset_data()

void libMesh::ExodusII_IO_Helper::write_sideset_data ( const MeshBase &  mesh,
int  timestep,
const std::vector< std::string > &  var_names,
const std::vector< std::set< boundary_id_type > > &  side_ids,
const std::vector< std::map< BoundaryInfo::BCTuple, Real > > &  bc_vals 
)

Write sideset data for the requested timestep.

Definition at line 4308 of file exodusII_io_helper.C.

4314{
4315 LOG_SCOPE("write_sideset_data()", "ExodusII_IO_Helper");
4316
4317 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4318 return;
4319
4320 // Write the sideset variable names to file. This function should
4321 // only be called once for SIDESET variables, repeated calls to
4322 // write_var_names overwrites/changes the order of names that were
4323 // there previously, and will mess up any data that has already been
4324 // written.
4325 this->write_var_names(SIDESET, var_names);
4326
4327 // I hope that we are allowed to call read_sideset_info() even
4328 // though we are in the middle of writing? It seems to work provided
4329 // that you have already written the mesh itself... read_sideset_info()
4330 // fills in the following data members:
4331 // .) num_side_sets
4332 // .) ss_ids
4333 this->read_sideset_info();
4334
4335 // Write "truth" table for sideset variables. The function
4336 // exII::ex_put_variable_param() must be called before
4337 // exII::ex_put_truth_table(). For us, this happens during the call
4338 // to ExodusII_IO_Helper::write_var_names(). sset_var_tab is a logically
4339 // (num_side_sets x num_sset_var) integer array of 0s and 1s
4340 // indicating which sidesets a given sideset variable is defined on.
4341 std::vector<int> sset_var_tab(num_side_sets * var_names.size());
4342
4343 // We now call read_sideset() once per sideset and write any sideset
4344 // variable values which are defined there.
4345 int offset=0;
4346 for (int ss=0; ss<num_side_sets; ++ss)
4347 {
4348 // We don't know num_sides_per_set for each set until we call
4349 // read_sideset(). The values for each sideset are stored (using
4350 // the offsets) into the 'elem_list' and 'side_list' arrays of
4351 // this class.
4352 offset += (ss > 0 ? num_sides_per_set[ss-1] : 0);
4353 this->read_sideset(ss, offset);
4354
4355 // For each variable in var_names, write the values for the
4356 // current sideset, if any.
4357 for (auto var : index_range(var_names))
4358 {
4359 // If this var has no values on this sideset, go to the next one.
4360 if (!side_ids[var].count(ss_ids[ss]))
4361 continue;
4362
4363 // Otherwise, fill in this entry of the sideset truth table.
4364 sset_var_tab[ss*var_names.size() + var] = 1;
4365
4366 // Data vector that will eventually be passed to exII::ex_put_var().
4367 std::vector<Real> sset_var_vals(num_sides_per_set[ss]);
4368
4369 // Get reference to the BCTuple -> Real map for this variable.
4370 const auto & data_map = bc_vals[var];
4371
4372 // Loop over elem_list, side_list entries in current sideset.
4373 for (int i=0; i<num_sides_per_set[ss]; ++i)
4374 {
4375 // Get elem_id and side_id from the respective lists that
4376 // are filled in by calling read_sideset().
4377 //
4378 // Note: these are Exodus-specific ids, so we have to convert them
4379 // to libmesh ids, as that is what will be in the bc_tuples.
4380 //
4381 // TODO: we should probably consult the exodus_elem_num_to_libmesh
4382 // mapping in order to figure out which libmesh element id 'elem_id'
4383 // actually corresponds to here, instead of just assuming it will be
4384 // off by one. Unfortunately that data structure does not seem to
4385 // be used at the moment. If we assume that write_sideset_data() is
4386 // always called following write(), then this should be a fairly safe
4387 // assumption...
4388 dof_id_type elem_id = elem_list[i + offset] - 1;
4389 unsigned int side_id = side_list[i + offset] - 1;
4390
4391 // Sanity check: make sure that the "off by one"
4392 // assumption we used above to set 'elem_id' is valid.
4393 libmesh_error_msg_if
4394 (libmesh_map_find(libmesh_elem_num_to_exodus, cast_int<int>(elem_id)) !=
4395 cast_int<dof_id_type>(elem_list[i + offset]),
4396 "Error mapping Exodus elem id to libmesh elem id.");
4397
4398 // Map from Exodus side ids to libmesh side ids.
4399 const auto & conv = get_conversion(mesh.elem_ptr(elem_id)->type());
4400
4401 // Map from Exodus side ids to libmesh side ids.
4402 unsigned int converted_side_id = conv.get_side_map(side_id);
4403
4404 // Construct a key so we can quickly see whether there is any
4405 // data for this variable in the map.
4406 BoundaryInfo::BCTuple key = std::make_tuple
4407 (elem_id,
4408 converted_side_id,
4409 ss_ids[ss]);
4410
4411 // Find the data for this (elem,side,id) tuple. Throw an
4412 // error if not found. Then store value in vector which
4413 // will be passed to Exodus.
4414 sset_var_vals[i] = libmesh_map_find(data_map, key);
4415 } // end for (i)
4416
4417 // As far as I can tell, there is no "concat" version of writing
4418 // sideset data, you have to call ex_put_sset_var() once per (variable,
4419 // sideset) pair.
4420 if (sset_var_vals.size() > 0)
4421 {
4422 ex_err = exII::ex_put_var
4423 (ex_id,
4424 timestep,
4425 exII::EX_SIDE_SET,
4426 var + 1, // 1-based variable index of current variable
4427 ss_ids[ss],
4429 MappedOutputVector(sset_var_vals, _single_precision).data());
4430 EX_CHECK_ERR(ex_err, "Error writing sideset vars.");
4431 }
4432 } // end for (var)
4433 } // end for (ss)
4434
4435 // Finally, write the sideset truth table.
4436 ex_err =
4437 exII::ex_put_truth_table(ex_id,
4438 exII::EX_SIDE_SET,
4440 cast_int<int>(var_names.size()),
4441 sset_var_tab.data());
4442 EX_CHECK_ERR(ex_err, "Error writing sideset var truth table.");
4443}
void read_sideset(int id, int offset)
Reads information about sideset id and inserts it into the global sideset array at the position offse...
void read_sideset_info()
Reads information about all of the sidesets in the ExodusII mesh file.
const boundary_id_type side_id

References _run_only_on_proc0, _single_precision, elem_list, libMesh::MeshBase::elem_ptr(), ex_err, ex_id, get_conversion(), libMesh::index_range(), libmesh_elem_num_to_exodus, mesh, num_side_sets, num_sides_per_set, libMesh::ParallelObject::processor_id(), read_sideset(), read_sideset_info(), side_id, side_list, SIDESET, ss_ids, libMesh::Elem::type(), and write_var_names().

◆ write_sidesets()

void libMesh::ExodusII_IO_Helper::write_sidesets ( const MeshBase &  mesh)
virtual

Writes the sidesets contained in "mesh".

We need to build up active elements if AMR is enabled and add them to the exodus sidesets instead of the potentially inactive "parent" elements

We need to build up active elements if AMR is enabled and add them to the exodus sidesets instead of the potentially inactive "parent" elements

Reimplemented in libMesh::Nemesis_IO_Helper.

Definition at line 3800 of file exodusII_io_helper.C.

3801{
3802 LOG_SCOPE("write_sidesets()", "ExodusII_IO_Helper");
3803
3804 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3805 return;
3806
3807 // Maps from sideset id to lists of corresponding element ids and side ids
3808 std::map<int, std::vector<int>> elem_lists;
3809 std::map<int, std::vector<int>> side_lists;
3810 std::set<boundary_id_type> side_boundary_ids;
3811
3812 {
3813 // Accumulate the vectors to pass into ex_put_side_set
3814 // build_side_lists() returns a vector of (elem, side, bc) tuples.
3815 for (const auto & t : mesh.get_boundary_info().build_side_list())
3816 {
3817 std::vector<const Elem *> family;
3818#ifdef LIBMESH_ENABLE_AMR
3823 mesh.elem_ref(std::get<0>(t)).active_family_tree_by_side(family, std::get<1>(t), false);
3824#else
3825 family.push_back(mesh.elem_ptr(std::get<0>(t)));
3826#endif
3827
3828 for (const auto & f : family)
3829 {
3830 const auto & conv = get_conversion(mesh.elem_ptr(f->id())->type());
3831
3832 // Use the libmesh to exodus data structure map to get the proper sideset IDs
3833 // The data structure contains the "collapsed" contiguous ids
3834 elem_lists[std::get<2>(t)].push_back(libmesh_elem_num_to_exodus[f->id()]);
3835 side_lists[std::get<2>(t)].push_back(conv.get_inverse_side_map(std::get<1>(t)));
3836 }
3837 }
3838
3839 std::vector<boundary_id_type> tmp;
3841 side_boundary_ids.insert(tmp.begin(), tmp.end());
3842 }
3843
3844 {
3845 // add data for shell faces, if needed
3846
3847 // Accumulate the vectors to pass into ex_put_side_set
3848 for (const auto & t : mesh.get_boundary_info().build_shellface_list())
3849 {
3850 std::vector<const Elem *> family;
3851#ifdef LIBMESH_ENABLE_AMR
3856 mesh.elem_ref(std::get<0>(t)).active_family_tree_by_side(family, std::get<1>(t), false);
3857#else
3858 family.push_back(mesh.elem_ptr(std::get<0>(t)));
3859#endif
3860
3861 for (const auto & f : family)
3862 {
3863 const auto & conv = get_conversion(mesh.elem_ptr(f->id())->type());
3864
3865 // Use the libmesh to exodus data structure map to get the proper sideset IDs
3866 // The data structure contains the "collapsed" contiguous ids
3867 elem_lists[std::get<2>(t)].push_back(libmesh_elem_num_to_exodus[f->id()]);
3868 side_lists[std::get<2>(t)].push_back(conv.get_inverse_shellface_map(std::get<1>(t)));
3869 }
3870 }
3871
3872 std::vector<boundary_id_type> tmp;
3874 side_boundary_ids.insert(tmp.begin(), tmp.end());
3875 }
3876
3877 // Add any empty-but-named side boundary ids
3878 for (const auto & pr : mesh.get_boundary_info().get_sideset_name_map())
3879 side_boundary_ids.insert(pr.first);
3880
3881 // Write out the sideset names, but only if there is something to write
3882 if (side_boundary_ids.size() > 0)
3883 {
3884 NamesData names_table(side_boundary_ids.size(), _max_name_length);
3885
3886 std::vector<exII::ex_set> sets(side_boundary_ids.size());
3887
3888 // Loop over "side_boundary_ids" and "sets" simultaneously
3889 for (auto [i, it] = std::tuple{0u, side_boundary_ids.begin()}; i<sets.size(); ++i, ++it)
3890 {
3891 boundary_id_type ss_id = *it;
3892 names_table.push_back_entry(mesh.get_boundary_info().get_sideset_name(ss_id));
3893
3894 sets[i].id = ss_id;
3895 sets[i].type = exII::EX_SIDE_SET;
3896 sets[i].num_distribution_factor = 0;
3897 sets[i].distribution_factor_list = nullptr;
3898
3899 if (const auto elem_it = elem_lists.find(ss_id);
3900 elem_it == elem_lists.end())
3901 {
3902 sets[i].num_entry = 0;
3903 sets[i].entry_list = nullptr;
3904 sets[i].extra_list = nullptr;
3905 }
3906 else
3907 {
3908 sets[i].num_entry = elem_it->second.size();
3909 sets[i].entry_list = elem_it->second.data();
3910 sets[i].extra_list = libmesh_map_find(side_lists, ss_id).data();
3911 }
3912 }
3913
3914 ex_err = exII::ex_put_sets(ex_id, side_boundary_ids.size(), sets.data());
3915 EX_CHECK_ERR(ex_err, "Error writing sidesets");
3916
3917 ex_err = exII::ex_put_names(ex_id, exII::EX_SIDE_SET, names_table.get_char_star_star());
3918 EX_CHECK_ERR(ex_err, "Error writing sideset names");
3919 }
3920}
const std::string & get_sideset_name(boundary_id_type id) const
void active_family_tree_by_side(std::vector< const Elem * > &family, unsigned int side, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to side.
Definition elem.C:2296

References _max_name_length, _run_only_on_proc0, libMesh::BoundaryInfo::build_shellface_boundary_ids(), libMesh::BoundaryInfo::build_shellface_list(), libMesh::BoundaryInfo::build_side_boundary_ids(), libMesh::BoundaryInfo::build_side_list(), libMesh::MeshBase::elem_ptr(), libMesh::MeshBase::elem_ref(), ex_err, ex_id, libMesh::MeshBase::get_boundary_info(), libMesh::ExodusII_IO_Helper::NamesData::get_char_star_star(), get_conversion(), libMesh::BoundaryInfo::get_sideset_name(), libMesh::BoundaryInfo::get_sideset_name_map(), libmesh_elem_num_to_exodus, mesh, libMesh::ParallelObject::processor_id(), libMesh::ExodusII_IO_Helper::NamesData::push_back_entry(), and libMesh::Elem::type().

◆ write_timestep()

void libMesh::ExodusII_IO_Helper::write_timestep ( int  timestep,
Real  time 
)

Writes the time for the timestep.

Definition at line 4189 of file exodusII_io_helper.C.

4190{
4191 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4192 return;
4193
4195 {
4196 float cast_time = float(time);
4197 ex_err = exII::ex_put_time(ex_id, timestep, &cast_time);
4198 }
4199 else
4200 {
4201 double cast_time = double(time);
4202 ex_err = exII::ex_put_time(ex_id, timestep, &cast_time);
4203 }
4204 EX_CHECK_ERR(ex_err, "Error writing timestep.");
4205
4206 this->update();
4207}

References _run_only_on_proc0, _single_precision, ex_err, ex_id, libMesh::ParallelObject::processor_id(), and update().

◆ write_var_names()

void libMesh::ExodusII_IO_Helper::write_var_names ( ExodusVarType  type,
const std::vector< std::string > &  names 
)
protected

Wraps calls to exII::ex_put_var_names() and exII::ex_put_var_param().

The enumeration controls whether nodal, elemental, or global variable names are read and which class members are filled in.

Definition at line 2326 of file exodusII_io_helper.C.

2328{
2329 switch (type)
2330 {
2331 case NODAL:
2332 this->write_var_names_impl("n", num_nodal_vars, names);
2333 break;
2334 case ELEMENTAL:
2335 this->write_var_names_impl("e", num_elem_vars, names);
2336 break;
2337 case GLOBAL:
2338 this->write_var_names_impl("g", num_global_vars, names);
2339 break;
2340 case SIDESET:
2341 {
2342 // Note: calling this function *sets* num_sideset_vars to the
2343 // number of entries in the 'names' vector, num_sideset_vars
2344 // does not already need to be set before calling this.
2345 this->write_var_names_impl("s", num_sideset_vars, names);
2346 break;
2347 }
2348 case NODESET:
2349 {
2350 this->write_var_names_impl("m", num_nodeset_vars, names);
2351 break;
2352 }
2353 case ELEMSET:
2354 {
2355 this->write_var_names_impl("t", num_elemset_vars, names);
2356 break;
2357 }
2358 default:
2359 libmesh_error_msg("Unrecognized ExodusVarType " << type);
2360 }
2361}
void write_var_names_impl(const char *var_type, int &count, const std::vector< std::string > &names)
write_var_names() dispatches to this function.

References ELEMENTAL, ELEMSET, GLOBAL, NODAL, NODESET, num_elem_vars, num_elemset_vars, num_global_vars, num_nodal_vars, num_nodeset_vars, num_sideset_vars, SIDESET, and write_var_names_impl().

Referenced by initialize_element_variables(), libMesh::Nemesis_IO_Helper::initialize_element_variables(), initialize_global_variables(), initialize_nodal_variables(), write_elemset_data(), write_nodeset_data(), and write_sideset_data().

◆ write_var_names_impl()

void libMesh::ExodusII_IO_Helper::write_var_names_impl ( const char *  var_type,
int &  count,
const std::vector< std::string > &  names 
)
private

write_var_names() dispatches to this function.

Definition at line 2366 of file exodusII_io_helper.C.

2369{
2370 // Update the count variable so that it's available to other parts of the class.
2371 count = cast_int<int>(names.size());
2372
2373 // Write that number of variables to the file.
2374 ex_err = exII::ex_put_var_param(ex_id, var_type, count);
2375 EX_CHECK_ERR(ex_err, "Error setting number of vars.");
2376
2377 // Nemesis doesn't like trying to write nodal variable names in
2378 // files with no nodes.
2379 if (!this->num_nodes)
2380 return;
2381
2382 if (count > 0)
2383 {
2384 NamesData names_table(count, _max_name_length);
2385
2386 // Store the input names in the format required by Exodus.
2387 for (int i=0; i != count; ++i)
2388 {
2389 if(names[i].length() > _max_name_length)
2390 libmesh_warning(
2391 "*** Warning, Exodus variable name \"" <<
2392 names[i] << "\" too long (current max " <<
2393 _max_name_length << "/" << libmesh_max_str_length <<
2394 " characters). Name will be truncated. ");
2395 names_table.push_back_entry(names[i]);
2396 }
2397
2398 if (verbose)
2399 {
2400 libMesh::out << "Writing variable name(s) to file: " << std::endl;
2401 for (int i=0; i != count; ++i)
2402 libMesh::out << names_table.get_char_star(i) << std::endl;
2403 }
2404
2405 ex_err = exII::ex_put_var_names(ex_id,
2406 var_type,
2407 count,
2408 names_table.get_char_star_star()
2409 );
2410
2411 EX_CHECK_ERR(ex_err, "Error writing variable names.");
2412 }
2413}

References _max_name_length, ex_err, ex_id, libMesh::ExodusII_IO_Helper::NamesData::get_char_star(), libMesh::ExodusII_IO_Helper::NamesData::get_char_star_star(), num_nodes, libMesh::out, libMesh::ExodusII_IO_Helper::NamesData::push_back_entry(), and verbose.

Referenced by write_var_names().

Member Data Documentation

◆ _add_sides

bool libMesh::ExodusII_IO_Helper::_add_sides = false
private

Set to true iff we want to write separate "side" elements too.

Definition at line 1133 of file exodusII_io_helper.h.

Referenced by get_add_sides(), initialize(), set_add_sides(), write_elements(), and write_nodal_coordinates().

◆ _added_side_node_offsets

std::vector<dof_id_type> libMesh::ExodusII_IO_Helper::_added_side_node_offsets
protected

If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS variables, _added_side_node_offsets[p] gives us the total solution vector offset to use on processor p+1 from the nodes on those previous ranks' sides.

Definition at line 1055 of file exodusII_io_helper.h.

Referenced by added_node_offset_on(), initialize(), and node_id_to_vec_id().

◆ _communicator

const Parallel::Communicator& libMesh::ParallelObject::_communicator
protectedinherited

◆ _coordinate_offset

Point libMesh::ExodusII_IO_Helper::_coordinate_offset
protected

Definition at line 1044 of file exodusII_io_helper.h.

Referenced by set_coordinate_offset(), and write_nodal_coordinates().

◆ _elem_vars_initialized

bool libMesh::ExodusII_IO_Helper::_elem_vars_initialized
protected

◆ _end_elem_id

int libMesh::ExodusII_IO_Helper::_end_elem_id
protected

Definition at line 1037 of file exodusII_io_helper.h.

Referenced by end_elem_id(), and read_elem_num_map().

◆ _global_vars_initialized

bool libMesh::ExodusII_IO_Helper::_global_vars_initialized
protected

Definition at line 1019 of file exodusII_io_helper.h.

Referenced by initialize_global_variables().

◆ _max_name_length

unsigned int libMesh::ExodusII_IO_Helper::_max_name_length
protected

◆ _nodal_vars_initialized

bool libMesh::ExodusII_IO_Helper::_nodal_vars_initialized
protected

Definition at line 1022 of file exodusII_io_helper.h.

Referenced by initialize_nodal_variables().

◆ _opened_by_create

bool libMesh::ExodusII_IO_Helper::_opened_by_create
protected

Definition at line 1013 of file exodusII_io_helper.h.

Referenced by close(), and create().

◆ _run_only_on_proc0

bool libMesh::ExodusII_IO_Helper::_run_only_on_proc0
protected

◆ _single_precision

bool libMesh::ExodusII_IO_Helper::_single_precision
protected

◆ _true_node_offsets

std::vector<dof_id_type> libMesh::ExodusII_IO_Helper::_true_node_offsets
protected

If we're adding "fake" sides to visualize SIDE_DISCONTINUOUS variables, we also need to know how many real nodes from previous ranks are taking up space in a solution vector.

Definition at line 1062 of file exodusII_io_helper.h.

Referenced by added_node_offset_on(), initialize(), and node_id_to_vec_id().

◆ _use_mesh_dimension_instead_of_spatial_dimension

bool libMesh::ExodusII_IO_Helper::_use_mesh_dimension_instead_of_spatial_dimension
protected

◆ _write_as_dimension

unsigned libMesh::ExodusII_IO_Helper::_write_as_dimension
protected

◆ _write_hdf5

bool libMesh::ExodusII_IO_Helper::_write_hdf5
protected

Definition at line 1031 of file exodusII_io_helper.h.

Referenced by create(), and set_hdf5_writing().

◆ bex_cv_conn

std::vector<std::vector<long unsigned int> > libMesh::ExodusII_IO_Helper::bex_cv_conn

Definition at line 852 of file exodusII_io_helper.h.

Referenced by read_elem_in_block().

◆ bex_dense_constraint_vecs

std::vector<std::vector<std::vector<Real> > > libMesh::ExodusII_IO_Helper::bex_dense_constraint_vecs

Definition at line 856 of file exodusII_io_helper.h.

Referenced by read_bex_cv_blocks().

◆ bex_num_elem_cvs

unsigned int libMesh::ExodusII_IO_Helper::bex_num_elem_cvs

Definition at line 849 of file exodusII_io_helper.h.

Referenced by read_elem_in_block().

◆ block_ids

std::vector<int> libMesh::ExodusII_IO_Helper::block_ids

◆ c0polyhedron_face_connect

std::vector<std::vector<int> > libMesh::ExodusII_IO_Helper::c0polyhedron_face_connect

Definition at line 770 of file exodusII_io_helper.h.

Referenced by open(), read_elem_in_block(), and read_face_blocks().

◆ connect

std::vector<int> libMesh::ExodusII_IO_Helper::connect

Definition at line 761 of file exodusII_io_helper.h.

Referenced by read_edge_blocks(), read_elem_in_block(), and write_elements().

◆ conversion_map

std::map<int, std::map<ElemType, ExodusII_IO_Helper::Conversion> > libMesh::ExodusII_IO_Helper::conversion_map
private

Associates libMesh ElemTypes with node/face/edge/etc.

mappings of the corresponding Exodus element types.

We have to map based on both ElemType and mesh dimension, because Exodus treats "TRI" side numbering in two different ways depending on whether a triangle is embedded in a 2D or a 3D mesh.

Definition at line 1157 of file exodusII_io_helper.h.

Referenced by get_conversion(), and init_conversion_map().

◆ current_filename

std::string libMesh::ExodusII_IO_Helper::current_filename

Definition at line 939 of file exodusII_io_helper.h.

Referenced by create(), and open().

◆ edge_block_ids

std::vector<int> libMesh::ExodusII_IO_Helper::edge_block_ids

Definition at line 758 of file exodusII_io_helper.h.

Referenced by read_block_info(), and read_edge_blocks().

◆ elem_face_counts

std::vector<int> libMesh::ExodusII_IO_Helper::elem_face_counts

Definition at line 767 of file exodusII_io_helper.h.

Referenced by open(), and read_elem_in_block().

◆ elem_list

std::vector<int> libMesh::ExodusII_IO_Helper::elem_list

◆ elem_node_counts

std::vector<int> libMesh::ExodusII_IO_Helper::elem_node_counts

Definition at line 764 of file exodusII_io_helper.h.

Referenced by open(), and read_elem_in_block().

◆ elem_num_map

std::vector<int> libMesh::ExodusII_IO_Helper::elem_num_map

◆ elem_type

std::vector<char> libMesh::ExodusII_IO_Helper::elem_type

◆ elem_var_names

std::vector<std::string> libMesh::ExodusII_IO_Helper::elem_var_names

◆ elem_var_values

std::vector<Real> libMesh::ExodusII_IO_Helper::elem_var_values

Definition at line 895 of file exodusII_io_helper.h.

◆ element_equivalence_map

std::map<std::string, ElemType> libMesh::ExodusII_IO_Helper::element_equivalence_map
private

Defines equivalence classes of Exodus element types that map to libmesh ElemTypes.

Definition at line 1146 of file exodusII_io_helper.h.

Referenced by get_conversion(), and init_element_equivalence_map().

◆ elemset_id_list

std::vector<int> libMesh::ExodusII_IO_Helper::elemset_id_list

Definition at line 828 of file exodusII_io_helper.h.

Referenced by read_elemset(), and read_elemset_info().

◆ elemset_ids

std::vector<int> libMesh::ExodusII_IO_Helper::elemset_ids

◆ elemset_list

std::vector<int> libMesh::ExodusII_IO_Helper::elemset_list

◆ elemset_var_names

std::vector<std::string> libMesh::ExodusII_IO_Helper::elemset_var_names

Definition at line 907 of file exodusII_io_helper.h.

Referenced by read_elemset_data(), and read_var_names().

◆ ex_err

int libMesh::ExodusII_IO_Helper::ex_err

◆ ex_id

int libMesh::ExodusII_IO_Helper::ex_id

Definition at line 677 of file exodusII_io_helper.h.

Referenced by close(), create(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), initialize(), initialize_element_variables(), libMesh::Nemesis_IO_Helper::initialize_element_variables(), open(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_eb_info_global(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_init_global(), libMesh::Nemesis_IO_Helper::put_init_info(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::Nemesis_IO_Helper::put_ns_param_global(), libMesh::Nemesis_IO_Helper::put_ss_param_global(), read_all_nodesets(), read_and_store_header_info(), read_bex_cv_blocks(), read_block_info(), read_edge_blocks(), read_elem_in_block(), read_elem_num_map(), read_elemental_var_values(), read_elemset(), read_elemset_data(), read_elemset_info(), read_face_blocks(), read_global_values(), read_header(), read_nodal_var_values(), read_node_num_map(), read_nodes(), libMesh::Nemesis_IO_Helper::read_nodeset(), read_nodeset_data(), read_nodeset_info(), read_qa_records(), read_sideset(), read_sideset_data(), read_sideset_info(), read_time_steps(), read_var_names_impl(), update(), libMesh::Nemesis_IO_Helper::write_element_values(), write_element_values(), write_element_values_element_major(), write_elements(), libMesh::Nemesis_IO_Helper::write_elements(), write_elemset_data(), write_elemsets(), libMesh::Nemesis_IO_Helper::write_exodus_initialization_info(), write_global_values(), write_information_records(), write_nodal_coordinates(), libMesh::Nemesis_IO_Helper::write_nodal_coordinates(), write_nodal_values(), write_nodeset_data(), write_nodesets(), libMesh::Nemesis_IO_Helper::write_nodesets(), write_sideset_data(), write_sidesets(), libMesh::Nemesis_IO_Helper::write_sidesets(), write_timestep(), write_var_names_impl(), and libMesh::Nemesis_IO_Helper::~Nemesis_IO_Helper().

◆ exodus_elem_num_to_libmesh

std::vector<int> libMesh::ExodusII_IO_Helper::exodus_elem_num_to_libmesh

◆ exodus_node_num_to_libmesh

std::vector<int> libMesh::ExodusII_IO_Helper::exodus_node_num_to_libmesh

◆ global_var_names

std::vector<std::string> libMesh::ExodusII_IO_Helper::global_var_names

Definition at line 898 of file exodusII_io_helper.h.

Referenced by initialize_global_variables(), and read_var_names().

◆ header_info

ExodusHeaderInfo libMesh::ExodusII_IO_Helper::header_info

Definition at line 683 of file exodusII_io_helper.h.

Referenced by read_and_store_header_info().

◆ id_list

std::vector<int> libMesh::ExodusII_IO_Helper::id_list

Definition at line 822 of file exodusII_io_helper.h.

Referenced by read_sideset(), and read_sideset_info().

◆ id_to_block_names

std::map<int, std::string> libMesh::ExodusII_IO_Helper::id_to_block_names

Definition at line 910 of file exodusII_io_helper.h.

Referenced by get_block_name(), and read_block_info().

◆ id_to_edge_block_names

std::map<int, std::string> libMesh::ExodusII_IO_Helper::id_to_edge_block_names

Definition at line 911 of file exodusII_io_helper.h.

Referenced by read_block_info(), and read_edge_blocks().

◆ id_to_elemset_names

std::map<int, std::string> libMesh::ExodusII_IO_Helper::id_to_elemset_names

Definition at line 914 of file exodusII_io_helper.h.

Referenced by read_elemset_info().

◆ id_to_ns_names

std::map<int, std::string> libMesh::ExodusII_IO_Helper::id_to_ns_names

Definition at line 913 of file exodusII_io_helper.h.

Referenced by get_node_set_name(), read_all_nodesets(), and read_nodeset_info().

◆ id_to_ss_names

std::map<int, std::string> libMesh::ExodusII_IO_Helper::id_to_ss_names

Definition at line 912 of file exodusII_io_helper.h.

Referenced by get_side_set_name(), and read_sideset_info().

◆ libmesh_elem_num_to_exodus

std::map<dof_id_type, dof_id_type> libMesh::ExodusII_IO_Helper::libmesh_elem_num_to_exodus

◆ libmesh_node_num_to_exodus

std::map<dof_id_type, dof_id_type> libMesh::ExodusII_IO_Helper::libmesh_node_num_to_exodus

◆ nodal_var_names

std::vector<std::string> libMesh::ExodusII_IO_Helper::nodal_var_names

◆ nodal_var_values

std::map<dof_id_type, Real> libMesh::ExodusII_IO_Helper::nodal_var_values

Definition at line 886 of file exodusII_io_helper.h.

Referenced by read_nodal_var_values().

◆ node_num_map

std::vector<int> libMesh::ExodusII_IO_Helper::node_num_map

◆ node_sets_dist_fact

std::vector<Real> libMesh::ExodusII_IO_Helper::node_sets_dist_fact

Definition at line 813 of file exodusII_io_helper.h.

Referenced by read_all_nodesets().

◆ node_sets_dist_index

std::vector<int> libMesh::ExodusII_IO_Helper::node_sets_dist_index

Definition at line 805 of file exodusII_io_helper.h.

Referenced by read_all_nodesets().

◆ node_sets_node_index

std::vector<int> libMesh::ExodusII_IO_Helper::node_sets_node_index

Definition at line 801 of file exodusII_io_helper.h.

Referenced by read_all_nodesets(), write_nodeset_data(), and write_nodesets().

◆ node_sets_node_list

std::vector<int> libMesh::ExodusII_IO_Helper::node_sets_node_list

◆ nodeset_ids

std::vector<int> libMesh::ExodusII_IO_Helper::nodeset_ids

◆ nodeset_var_names

std::vector<std::string> libMesh::ExodusII_IO_Helper::nodeset_var_names

Definition at line 904 of file exodusII_io_helper.h.

Referenced by read_nodeset_data(), and read_var_names().

◆ num_attr

int libMesh::ExodusII_IO_Helper::num_attr

Definition at line 746 of file exodusII_io_helper.h.

Referenced by read_elem_in_block().

◆ num_df_per_set

std::vector<int> libMesh::ExodusII_IO_Helper::num_df_per_set

Definition at line 791 of file exodusII_io_helper.h.

Referenced by read_sideset(), and read_sideset_info().

◆ num_dim

int& libMesh::ExodusII_IO_Helper::num_dim

◆ num_edge

int& libMesh::ExodusII_IO_Helper::num_edge

Definition at line 705 of file exodusII_io_helper.h.

Referenced by initialize().

◆ num_edge_blk

int& libMesh::ExodusII_IO_Helper::num_edge_blk

◆ num_elem

int& libMesh::ExodusII_IO_Helper::num_elem

◆ num_elem_all_elemsets

int libMesh::ExodusII_IO_Helper::num_elem_all_elemsets

Definition at line 752 of file exodusII_io_helper.h.

Referenced by read_elemset_info().

◆ num_elem_all_sidesets

int libMesh::ExodusII_IO_Helper::num_elem_all_sidesets

Definition at line 749 of file exodusII_io_helper.h.

Referenced by read_sideset_info().

◆ num_elem_blk

int& libMesh::ExodusII_IO_Helper::num_elem_blk

◆ num_elem_df_per_set

std::vector<int> libMesh::ExodusII_IO_Helper::num_elem_df_per_set

Definition at line 797 of file exodusII_io_helper.h.

Referenced by read_elemset(), and read_elemset_info().

◆ num_elem_sets

int& libMesh::ExodusII_IO_Helper::num_elem_sets

◆ num_elem_this_blk

int libMesh::ExodusII_IO_Helper::num_elem_this_blk

◆ num_elem_vars

int libMesh::ExodusII_IO_Helper::num_elem_vars

◆ num_elems_per_set

std::vector<int> libMesh::ExodusII_IO_Helper::num_elems_per_set

◆ num_elemset_vars

int libMesh::ExodusII_IO_Helper::num_elemset_vars

◆ num_face

int& libMesh::ExodusII_IO_Helper::num_face

Definition at line 712 of file exodusII_io_helper.h.

Referenced by initialize(), read_face_blocks(), and write_elements().

◆ num_face_blk

int& libMesh::ExodusII_IO_Helper::num_face_blk

Definition at line 716 of file exodusII_io_helper.h.

Referenced by initialize(), read_face_blocks(), and write_elements().

◆ num_global_vars

int libMesh::ExodusII_IO_Helper::num_global_vars

◆ num_nodal_vars

int libMesh::ExodusII_IO_Helper::num_nodal_vars

◆ num_node_df_per_set

std::vector<int> libMesh::ExodusII_IO_Helper::num_node_df_per_set

◆ num_node_sets

int& libMesh::ExodusII_IO_Helper::num_node_sets

◆ num_nodes

int& libMesh::ExodusII_IO_Helper::num_nodes

◆ num_nodes_per_elem

int libMesh::ExodusII_IO_Helper::num_nodes_per_elem

◆ num_nodes_per_set

std::vector<int> libMesh::ExodusII_IO_Helper::num_nodes_per_set

◆ num_nodeset_vars

int libMesh::ExodusII_IO_Helper::num_nodeset_vars

◆ num_side_sets

int& libMesh::ExodusII_IO_Helper::num_side_sets

◆ num_sides_per_set

std::vector<int> libMesh::ExodusII_IO_Helper::num_sides_per_set

◆ num_sideset_vars

int libMesh::ExodusII_IO_Helper::num_sideset_vars

◆ num_time_steps

int libMesh::ExodusII_IO_Helper::num_time_steps

Definition at line 872 of file exodusII_io_helper.h.

Referenced by read_num_time_steps(), and read_time_steps().

◆ opened_for_reading

bool libMesh::ExodusII_IO_Helper::opened_for_reading

Definition at line 929 of file exodusII_io_helper.h.

Referenced by close(), and open().

◆ opened_for_writing

bool libMesh::ExodusII_IO_Helper::opened_for_writing

◆ set_unique_ids_from_maps

bool libMesh::ExodusII_IO_Helper::set_unique_ids_from_maps

◆ side_list

std::vector<int> libMesh::ExodusII_IO_Helper::side_list

◆ sideset_var_names

std::vector<std::string> libMesh::ExodusII_IO_Helper::sideset_var_names

Definition at line 901 of file exodusII_io_helper.h.

Referenced by read_sideset_data(), and read_var_names().

◆ ss_ids

std::vector<int> libMesh::ExodusII_IO_Helper::ss_ids

◆ time_steps

std::vector<Real> libMesh::ExodusII_IO_Helper::time_steps

Definition at line 875 of file exodusII_io_helper.h.

Referenced by read_time_steps().

◆ title

std::vector<char>& libMesh::ExodusII_IO_Helper::title

Definition at line 686 of file exodusII_io_helper.h.

Referenced by ExodusII_IO_Helper(), and print_header().

◆ verbose

bool libMesh::ExodusII_IO_Helper::verbose

◆ w

std::vector<Real> libMesh::ExodusII_IO_Helper::w

Definition at line 846 of file exodusII_io_helper.h.

Referenced by read_nodes().

◆ x

std::vector<Real> libMesh::ExodusII_IO_Helper::x

◆ y

std::vector<Real> libMesh::ExodusII_IO_Helper::y

◆ z

std::vector<Real> libMesh::ExodusII_IO_Helper::z

The documentation for this class was generated from the following files: