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_Helperoperator= (const ExodusII_IO_Helper &)=delete
 This class contains references so it can't be default copy/move-assigned.
 
ExodusII_IO_Helperoperator= (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::Conversionget_conversion (const ElemType type) const
 
const ExodusII_IO_Helper::Conversionget_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::Communicatorcomm () 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
 
intnum_dim
 
intnum_nodes
 
intnum_elem
 
intnum_elem_blk
 
intnum_edge
 
intnum_edge_blk
 
intnum_face
 
intnum_face_blk
 
intnum_node_sets
 
intnum_side_sets
 
intnum_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< intblock_ids
 
std::vector< intedge_block_ids
 
std::vector< intconnect
 
std::vector< intelem_node_counts
 
std::vector< intelem_face_counts
 
std::vector< std::vector< int > > c0polyhedron_face_connect
 
std::vector< intss_ids
 
std::vector< intnodeset_ids
 
std::vector< intelemset_ids
 
std::vector< intnum_sides_per_set
 
std::vector< intnum_nodes_per_set
 
std::vector< intnum_elems_per_set
 
std::vector< intnum_df_per_set
 
std::vector< intnum_node_df_per_set
 
std::vector< intnum_elem_df_per_set
 
std::vector< intnode_sets_node_index
 
std::vector< intnode_sets_dist_index
 
std::vector< intnode_sets_node_list
 
std::vector< Realnode_sets_dist_fact
 
std::vector< intelem_list
 
std::vector< intside_list
 
std::vector< intid_list
 
std::vector< intelemset_list
 
std::vector< intelemset_id_list
 
std::vector< intnode_num_map
 
std::vector< intelem_num_map
 
std::vector< Realx
 
std::vector< Realy
 
std::vector< Realz
 
std::vector< Realw
 
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_typelibmesh_elem_num_to_exodus
 
std::vector< intexodus_elem_num_to_libmesh
 
std::map< dof_id_type, dof_id_typelibmesh_node_num_to_exodus
 
std::vector< intexodus_node_num_to_libmesh
 
int num_time_steps
 
std::vector< Realtime_steps
 
int num_nodal_vars
 
std::vector< std::string > nodal_var_names
 
std::map< dof_id_type, Realnodal_var_values
 
int num_elem_vars
 
std::vector< std::string > elem_var_names
 
std::vector< Realelem_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, ElemTypeelement_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 271 of file exodusII_io_helper.C.

274 :
275 ParallelObject(parent),
276 ex_id(0),
277 ex_err(0),
278 header_info(), // zero-initialize
297 num_attr(0),
303 num_elem_vars(0),
304 verbose(v),
306 opened_for_writing(false),
307 opened_for_reading(false),
308 _run_only_on_proc0(run_only_on_proc0),
309 _opened_by_create(false),
314 _write_hdf5(true),
316 _end_elem_id(0),
318 _single_precision(single_precision)
319{
320 title.resize(MAX_LINE_LENGTH+1);
321 elem_type.resize(libmesh_max_str_length);
324}
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 4022 of file exodusII_io_helper.C.

4025{
4026 // There may already be global variables in the file (for example,
4027 // if we're appending) and in that case, we
4028 // 1.) Cannot initialize them again.
4029 // 2.) Should check to be sure that the global variable names are the same.
4030
4031 // Fills up names_from_file for us
4032 this->read_var_names(type);
4033
4034 // Both the number of variables and their names (up to the first
4035 // MAX_STR_LENGTH characters) must match for the names we are
4036 // planning to write and the names already in the file.
4037 bool match =
4038 std::equal(names.begin(), names.end(),
4039 names_from_file.begin(),
4040 [this](const std::string & a,
4041 const std::string & b) -> bool
4042 {
4043 return a.compare(/*pos=*/0, /*len=*/_max_name_length, b) == 0;
4044 });
4045
4046 if (!match)
4047 {
4048 libMesh::err << "Error! The Exodus file already contains the variables:" << std::endl;
4049 for (const auto & name : names_from_file)
4050 libMesh::err << name << std::endl;
4051
4052 libMesh::err << "And you asked to write:" << std::endl;
4053 for (const auto & name : names)
4054 libMesh::err << name << std::endl;
4055
4056 libmesh_error_msg("Cannot overwrite existing variables in Exodus II file.");
4057 }
4058}
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 2040 of file exodusII_io_helper.C.

2041{
2042 // Call ex_close on every processor that did ex_open or ex_create;
2043 // newer Exodus versions error if we try to reopen a file that
2044 // hasn't been officially closed. Don't close the file if we didn't
2045 // open it; this also raises an Exodus error.
2046
2047 // We currently do read-only ex_open on every proc (to do read
2048 // operations on every proc), but we do ex_open and ex_create for
2049 // writes on every proc only with Nemesis files.
2051 (this->processor_id() == 0) ||
2053 {
2055 {
2056 ex_err = exII::ex_close(ex_id);
2057 // close() is called from the destructor, so it may be called e.g.
2058 // during stack unwinding while processing an exception. In that case
2059 // we don't want to throw another exception or immediately terminate
2060 // the code, since that would prevent any possible recovery from the
2061 // exception in question. So we just log the error closing the file
2062 // and continue.
2063 if (ex_err < 0)
2064 message("Error closing Exodus file.");
2065 else
2066 message("Exodus file closed successfully.");
2067 }
2068 }
2069
2070 // Now that the file is closed, it's no longer opened for
2071 // reading or writing.
2072 opened_for_writing = false;
2073 opened_for_reading = false;
2074 _opened_by_create = false;
2075}
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 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::MeshBase::cache_elem_data(), libMesh::DofMap::check_dirichlet_bcid_consistency(), libMesh::MeshTetInterface::check_hull_integrity(), 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::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_mffd_interface(), 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::MeshBase::n_constraint_rows(), 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(), 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(), 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 2469 of file exodusII_io_helper.C.

2471{
2472 this->set_dof_object_unique_id(mesh, elem, libmesh_vector_at(this->elem_num_map, zero_based_elem_num_map_index));
2473}
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 2462 of file exodusII_io_helper.C.

2464{
2465 this->set_dof_object_unique_id(mesh, node, libmesh_vector_at(this->node_num_map, zero_based_node_num_map_index));
2466}

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 2513 of file exodusII_io_helper.C.

2514{
2515 // If we're processor 0, always create the file.
2516 // If we running on all procs, e.g. as one of several Nemesis files, also
2517 // call create there.
2518 if ((this->processor_id() == 0) || (!_run_only_on_proc0))
2519 {
2520 int
2521 comp_ws = 0,
2522 io_ws = 0;
2523
2525 {
2526 comp_ws = cast_int<int>(sizeof(float));
2527 io_ws = cast_int<int>(sizeof(float));
2528 }
2529 // Fall back on double precision when necessary since ExodusII
2530 // doesn't seem to support long double
2531 else
2532 {
2533 comp_ws = cast_int<int>
2534 (std::min(sizeof(Real), sizeof(double)));
2535 io_ws = cast_int<int>
2536 (std::min(sizeof(Real), sizeof(double)));
2537 }
2538
2539 // By default we just open the Exodus file in "EX_CLOBBER" mode,
2540 // which, according to "ncdump -k", writes the file in "64-bit
2541 // offset" mode, which is a NETCDF3 file format.
2542 int mode = EX_CLOBBER;
2543
2544 // If HDF5 is available, by default we will write Exodus files
2545 // in a more modern NETCDF4-compatible format. For this file
2546 // type, "ncdump -k" will report "netCDF-4".
2547#ifdef LIBMESH_HAVE_HDF5
2548 if (this->_write_hdf5)
2549 {
2550 mode |= EX_NETCDF4;
2551 mode |= EX_NOCLASSIC;
2552 }
2553#endif
2554
2555 {
2556 FPEDisabler disable_fpes;
2557 ex_id = exII::ex_create(filename.c_str(), mode, &comp_ws, &io_ws);
2558 }
2559
2560 EX_CHECK_ERR(ex_id, "Error creating ExodusII/Nemesis mesh file.");
2561
2562 // We don't have access to the names we might be writing until we
2563 // write them, so we can't set a guaranteed max name length here.
2564 // But it looks like the most ExodusII can support is 80, so we'll
2565 // just waste 48 bytes here and there.
2566 ex_err = exII::ex_set_max_name_length(ex_id, _max_name_length);
2567 EX_CHECK_ERR(ex_err, "Error setting max ExodusII name length.");
2568
2569 if (verbose)
2570 libMesh::out << "File created successfully." << std::endl;
2571 }
2572
2573 opened_for_writing = true;
2574 _opened_by_create = true;
2575 current_filename = filename;
2576}
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.

◆ 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 1149 of file exodusII_io_helper.C.

1150{
1151 libmesh_assert_less (index, block_ids.size());
1152
1153 return block_ids[index];
1154}

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 1158 of file exodusII_io_helper.C.

1159{
1160 libmesh_assert_less (index, block_ids.size());
1161
1162 return id_to_block_names[block_ids[index]];
1163}
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 5379 of file exodusII_io_helper.C.

5381{
5382 std::vector<std::string> complex_names;
5383
5384 // This will loop over all names and create new "complex" names
5385 // (i.e. names that start with r_, i_ or a_)
5386 for (const auto & name : names)
5387 {
5388 complex_names.push_back("r_" + name);
5389 complex_names.push_back("i_" + name);
5390 if (write_complex_abs)
5391 complex_names.push_back("a_" + name);
5392 }
5393
5394 return complex_names;
5395}

◆ 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 5423 of file exodusII_io_helper.C.

5427{
5428 // Eventual return value
5429 std::map<subdomain_id_type, std::vector<std::string>> ret;
5430
5431 unsigned int num_complex_outputs = write_complex_abs ? 3 : 2;
5432
5433 for (const auto & pr : subdomain_to_var_names)
5434 {
5435 // Initialize entry for current subdomain
5436 auto & vec = ret[pr.first];
5437
5438 // Get list of non-complex variable names active on this subdomain.
5439 const auto & varnames = pr.second;
5440
5441 // Allocate space for the complex-valued entries
5442 vec.reserve(num_complex_outputs * varnames.size());
5443
5444 // For each varname in the input map, write three variable names
5445 // to the output formed by prepending "r_", "i_", and "a_",
5446 // respectively.
5447 for (const auto & varname : varnames)
5448 {
5449 vec.push_back("r_" + varname);
5450 vec.push_back("i_" + varname);
5451 if (write_complex_abs)
5452 vec.push_back("a_" + varname);
5453 }
5454 }
5455 return ret;
5456}

◆ 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 5400 of file exodusII_io_helper.C.

5404{
5405 std::vector<std::set<subdomain_id_type>> complex_vars_active_subdomains;
5406
5407 for (auto & s : vars_active_subdomains)
5408 {
5409 // Push back the same data enough times for the real, imag, (and
5410 // possibly modulus) for the complex-valued solution.
5411 complex_vars_active_subdomains.push_back(s);
5412 complex_vars_active_subdomains.push_back(s);
5413 if (write_complex_abs)
5414 complex_vars_active_subdomains.push_back(s);
5415 }
5416
5417 return complex_vars_active_subdomains;
5418}

◆ get_conversion() [1/2]

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

Definition at line 572 of file exodusII_io_helper.C.

573{
574 auto & maps_for_dim = libmesh_map_find(conversion_map, this->num_dim);
575 return libmesh_map_find(maps_for_dim, type);
576}
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 579 of file exodusII_io_helper.C.

580{
581 // Do only upper-case comparisons
582 std::transform(type_str.begin(), type_str.end(), type_str.begin(), ::toupper);
583 return get_conversion (libmesh_map_find(element_equivalence_map, type_str));
584}
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 586 of file exodusII_io_helper.C.

587{
588 return elem_type.data();
589}

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 4810 of file exodusII_io_helper.C.

4812{
4813 // Clear existing data, we are going to build these data structures from scratch
4814 elemset_array_indices.clear();
4815
4816 // Read the elemset data.
4817 //
4818 // Note: we assume that the functions
4819 // 1.) this->read_elemset_info() and
4820 // 2.) this->read_elemset()
4821 // have already been called, so that we already know e.g. how
4822 // many elems are in each set, their ids, etc.
4823 int offset=0;
4824 for (int es=0; es<num_elem_sets; ++es)
4825 {
4826 offset += (es > 0 ? num_elems_per_set[es-1] : 0);
4827
4828 // Note: we don't actually call exII::ex_get_var() here because
4829 // we don't need the values. We only need the indices into that vector
4830 // for each (elem_id, elemset_id) tuple.
4831 for (int i=0; i<num_elems_per_set[es]; ++i)
4832 {
4833 dof_id_type exodus_elem_id = elemset_list[i + offset];
4834
4835 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4836 // but it apparently is never set up, so just
4837 // subtract 1 from the Exodus elem id.
4838 dof_id_type converted_elem_id = exodus_elem_id - 1;
4839
4840 // Make key based on the elem and set ids
4841 // Make a NodeBCTuple key from the converted information.
4842 auto key = std::make_pair(converted_elem_id,
4843 static_cast<elemset_id_type>(elemset_ids[es]));
4844
4845 // Store the array index of this (node, b_id) tuple
4846 elemset_array_indices.emplace(key, cast_int<unsigned int>(i));
4847 } // end for (i)
4848 } // end for (es)
4849}
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 332 of file exodusII_io_helper.C.

333{
334 return EX_API_VERS_NODOT;
335}

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 2423 of file exodusII_io_helper.C.

2424{
2425 return this->get_libmesh_id(exodus_elem_id, this->elem_num_map);
2426}
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 2429 of file exodusII_io_helper.C.

2431{
2432 // The input exodus_id is assumed to be a (1-based) index into
2433 // the {node,elem}_num_map, so in order to use exodus_id as an index
2434 // in C++, we need to first make it zero-based.
2435 auto exodus_id_zero_based =
2436 cast_int<dof_id_type>(exodus_id - 1);
2437
2438 // Throw an informative error message rather than accessing past the
2439 // end of the provided num_map. If we are setting Elem unique_ids
2440 // based on the num_map, we don't need to do this check.
2441 if (!this->set_unique_ids_from_maps)
2442 libmesh_error_msg_if(exodus_id_zero_based >= num_map.size(),
2443 "Cannot get LibMesh id for Exodus id: " << exodus_id);
2444
2445 // If the user set the flag which stores Exodus node/elem ids as
2446 // unique_ids instead of regular ids, then the libmesh id we are
2447 // looking for is actually just "exodus_id_zero_based". Otherwise,
2448 // we need to look up the Node/Elem's id in the provided num_map,
2449 // *and* then subtract 1 from that because the entries in the
2450 // num_map are also 1-based.
2451 dof_id_type libmesh_id =
2453 cast_int<dof_id_type>(exodus_id_zero_based) :
2454 cast_int<dof_id_type>(num_map[exodus_id_zero_based] - 1);
2455
2456 return libmesh_id;
2457}
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 2418 of file exodusII_io_helper.C.

2419{
2420 return this->get_libmesh_id(exodus_node_id, this->node_num_map);
2421}

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 1185 of file exodusII_io_helper.C.

1186{
1187 libmesh_assert_less (index, nodeset_ids.size());
1188
1189 return nodeset_ids[index];
1190}

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 1194 of file exodusII_io_helper.C.

1195{
1196 libmesh_assert_less (index, nodeset_ids.size());
1197
1198 return id_to_ns_names[nodeset_ids[index]];
1199}
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 4952 of file exodusII_io_helper.C.

4954{
4955 // Clear existing data, we are going to build these data structures from scratch
4956 bc_array_indices.clear();
4957
4958 // Read the nodeset data.
4959 //
4960 // Note: we assume that the functions
4961 // 1.) this->read_nodeset_info() and
4962 // 2.) this->read_all_nodesets()
4963 // have already been called, so that we already know e.g. how
4964 // many nodes are in each set, their ids, etc.
4965 int offset=0;
4966 for (int ns=0; ns<num_node_sets; ++ns)
4967 {
4968 offset += (ns > 0 ? num_nodes_per_set[ns-1] : 0);
4969 // Note: we don't actually call exII::ex_get_var() here because
4970 // we don't need the values. We only need the indices into that vector
4971 // for each (node_id, boundary_id) tuple.
4972 for (int i=0; i<num_nodes_per_set[ns]; ++i)
4973 {
4974 // The read_all_nodesets() function now reads all the node ids into the
4975 // node_sets_node_list vector, which is of length "total_nodes_in_all_sets"
4976 // The old read_nodset() function is no longer called as far as I can tell,
4977 // and should probably be removed? The "offset" that we are using only
4978 // depends on the current nodeset index and the num_nodes_per_set vector,
4979 // which gets filled in by the call to read_all_nodesets().
4980 dof_id_type exodus_node_id = node_sets_node_list[i + offset];
4981
4982 // FIXME: We should use exodus_node_num_to_libmesh for this,
4983 // but it apparently is never set up, so just
4984 // subtract 1 from the Exodus node id.
4985 dof_id_type converted_node_id = exodus_node_id - 1;
4986
4987 // Make a NodeBCTuple key from the converted information.
4988 BoundaryInfo::NodeBCTuple key = std::make_tuple
4989 (converted_node_id, nodeset_ids[ns]);
4990
4991 // Store the array index of this (node, b_id) tuple
4992 bc_array_indices.emplace(key, cast_int<unsigned int>(i));
4993 } // end for (i)
4994 } // end for (ns)
4995}
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 1167 of file exodusII_io_helper.C.

1168{
1169 libmesh_assert_less (index, ss_ids.size());
1170
1171 return ss_ids[index];
1172}

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 1176 of file exodusII_io_helper.C.

1177{
1178 libmesh_assert_less (index, ss_ids.size());
1179
1180 return id_to_ss_names[ss_ids[index]];
1181}
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 4425 of file exodusII_io_helper.C.

4428{
4429 // Clear any existing data, we are going to build this data structure from scratch
4430 bc_array_indices.clear();
4431
4432 // Store the sideset data array indices.
4433 //
4434 // Note: we assume that read_sideset() has already been called
4435 // for each sideset, so the required values in elem_list and
4436 // side_list are already present.
4437 int offset=0;
4438 for (int ss=0; ss<num_side_sets; ++ss)
4439 {
4440 offset += (ss > 0 ? num_sides_per_set[ss-1] : 0);
4441 for (int i=0; i<num_sides_per_set[ss]; ++i)
4442 {
4443 dof_id_type exodus_elem_id = elem_list[i + offset];
4444 unsigned int exodus_side_id = side_list[i + offset];
4445
4446 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4447 // but it apparently is never set up, so just
4448 // subtract 1 from the Exodus elem id.
4449 dof_id_type converted_elem_id = exodus_elem_id - 1;
4450
4451 // Conversion operator for this Elem type
4452 const auto & conv = get_conversion(mesh.elem_ptr(converted_elem_id)->type());
4453
4454 // Map from Exodus side id to libmesh side id.
4455 // Note: the mapping is defined on 0-based indices, so subtract
4456 // 1 before doing the mapping.
4457 unsigned int converted_side_id = conv.get_side_map(exodus_side_id - 1);
4458
4459 // Make a BCTuple key from the converted information.
4460 BoundaryInfo::BCTuple key = std::make_tuple
4461 (converted_elem_id,
4462 converted_side_id,
4463 ss_ids[ss]);
4464
4465 // Store (elem, side, b_id) tuple with corresponding array index
4466 bc_array_indices.emplace(key, cast_int<unsigned int>(i));
4467 } // end for (i)
4468 } // end for (ss)
4469}
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 340 of file exodusII_io_helper.C.

341{
342 auto convert_type = [this](ElemType type,
343 std::string_view exodus_type,
344 const std::vector<int> * node_map = nullptr,
345 const std::vector<int> * inverse_node_map = nullptr,
346 const std::vector<int> * side_map = nullptr,
347 const std::vector<int> * inverse_side_map = nullptr,
348 const std::vector<int> * shellface_map = nullptr,
349 const std::vector<int> * inverse_shellface_map = nullptr,
350 size_t shellface_index_offset = 0)
351 {
352 std::unique_ptr<Elem> elem = Elem::build(type);
353 auto & conv = conversion_map[elem->dim()][type];
354 conv.libmesh_type = type;
355 conv.exodus_type = exodus_type;
356 conv.node_map = node_map;
357 conv.inverse_node_map = inverse_node_map;
358 conv.side_map = side_map;
359 conv.inverse_side_map = inverse_side_map;
360 conv.shellface_map = shellface_map;
361 conv.inverse_shellface_map = inverse_shellface_map;
362 conv.shellface_index_offset = shellface_index_offset;
363 conv.n_nodes = elem->n_nodes();
364 for (int d = elem->dim()+1; d <= 3; ++d)
365 conversion_map[d][type] = conv;
366 };
367
368 convert_type(NODEELEM, "SPHERE");
369 convert_type(EDGE2, "EDGE2");
370 convert_type(EDGE3, "EDGE3");
371 convert_type(EDGE4, "EDGE4");
372 convert_type(QUAD4, "QUAD4");
373 convert_type(QUAD8, "QUAD8");
374 convert_type(QUAD9, "QUAD9");
375 convert_type(C0POLYGON, "NSIDED");
376 {
377 auto & conv = conversion_map[3][C0POLYHEDRON];
378 conv.libmesh_type = C0POLYHEDRON;
379 conv.exodus_type = "NFACED";
380 conv.dim = 3;
381 conv.n_nodes = 0;
382 }
383 convert_type(QUADSHELL4, "SHELL4", nullptr, nullptr, nullptr,
384 /* inverse_side_map = */ &quadshell4_inverse_edge_map,
385 nullptr, nullptr, /* shellface_index_offset = */ 2);
386 convert_type(QUADSHELL8, "SHELL8", nullptr, nullptr, nullptr,
387 /* inverse_side_map = */ &quadshell4_inverse_edge_map,
388 nullptr, nullptr, /* shellface_index_offset = */ 2);
389 convert_type(QUADSHELL9, "SHELL9", nullptr, nullptr, nullptr,
390 /* inverse_side_map = */ &quadshell4_inverse_edge_map,
391 nullptr, nullptr, /* shellface_index_offset = */ 2);
392
393 convert_type(TRI3, "TRI3");
394 convert_type(TRI6, "TRI6");
395 convert_type(TRI7, "TRI7");
396 // Exodus does weird things to triangle side mapping in 3D. See
397 // https://sandialabs.github.io/seacas-docs/html/element_types.html#tri
398 conversion_map[3][TRI3].inverse_side_map = &trishell3_inverse_edge_map;
399 conversion_map[3][TRI3].shellface_index_offset = 2;
400 conversion_map[3][TRI6].inverse_side_map = &trishell3_inverse_edge_map;
401 conversion_map[3][TRI6].shellface_index_offset = 2;
402 conversion_map[3][TRI7].inverse_side_map = &trishell3_inverse_edge_map;
403 conversion_map[3][TRI7].shellface_index_offset = 2;
404
405 convert_type(TRISHELL3, "TRISHELL3", nullptr, nullptr, nullptr,
406 /* inverse_side_map = */ &trishell3_inverse_edge_map,
407 nullptr, nullptr, /* shellface_index_offset = */ 2);
408 convert_type(TRI3SUBDIVISION, "TRI3");
409 convert_type(HEX8, "HEX8", nullptr, nullptr,
410 &hex_face_map, &hex_inverse_face_map);
411 convert_type(HEX20, "HEX20", nullptr, nullptr,
412 &hex_face_map, &hex_inverse_face_map);
413 convert_type(HEX27, "HEX27", &hex27_node_map,
414 &hex27_inverse_node_map,
415 &hex_face_map, &hex_inverse_face_map);
416 convert_type(TET4, "TETRA4", nullptr, nullptr,
417 &tet_face_map, &tet_inverse_face_map);
418 convert_type(TET10, "TETRA10", nullptr, nullptr,
419 &tet_face_map, &tet_inverse_face_map);
420 convert_type(TET14, "TETRA14", &tet14_node_map,
421 &tet14_inverse_node_map,
422 &tet_face_map, &tet_inverse_face_map);
423 convert_type(PRISM6, "WEDGE", nullptr, nullptr,
424 &prism_face_map, &prism_inverse_face_map);
425 convert_type(PRISM15, "WEDGE15", nullptr, nullptr,
426 &prism_face_map, &prism_inverse_face_map);
427 convert_type(PRISM18, "WEDGE18", nullptr, nullptr,
428 &prism_face_map, &prism_inverse_face_map);
429 convert_type(PRISM20, "WEDGE20", &prism20_node_map,
430 &prism20_inverse_node_map,
431 &prism_face_map, &prism_inverse_face_map);
432 convert_type(PRISM21, "WEDGE21", &prism21_node_map,
433 &prism21_inverse_node_map,
434 &prism_face_map, &prism_inverse_face_map);
435 convert_type(PYRAMID5, "PYRAMID5");
436 convert_type(PYRAMID13, "PYRAMID13");
437 convert_type(PYRAMID14, "PYRAMID14");
438 convert_type(PYRAMID18, "PYRAMID18");
439}
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
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 445 of file exodusII_io_helper.C.

446{
447 // We use an ExodusII SPHERE element to represent a NodeElem
449
450 // EDGE2 equivalences
456 element_equivalence_map["TRUSS2"] = EDGE2;
459
460 // EDGE3 equivalences
462 element_equivalence_map["TRUSS3"] = EDGE3;
465
466 // EDGE4 equivalences
468 element_equivalence_map["TRUSS4"] = EDGE4;
471
472 // This whole design is going to need to be refactored whenever we
473 // support higher-order IGA, with one element type having variable
474 // polynomiaal degree...
475 element_equivalence_map["BEX_CURVE"] = EDGE3;
476
477 // QUAD4 equivalences
480
481 // QUADSHELL4 equivalences
484
485 // QUAD8 equivalences
487
488 // QUADSHELL8 equivalences
490
491 // QUAD9 equivalences
493 // This only supports p==2 IGA:
494 element_equivalence_map["BEX_QUAD"] = QUAD9;
495
496 // QUADSHELL9 equivalences
498
499 // Runtime-topology polytope equivalences
502
503 // TRI3 equivalences
506 element_equivalence_map["TRIANGLE"] = TRI3;
507
508 // TRISHELL3 equivalences
510 element_equivalence_map["TRISHELL3"] = TRISHELL3;
511
512 // TRI6 equivalences
514 // element_equivalence_map["TRISHELL6"] = TRI6;
515 // This only supports p==2 IGA:
516 element_equivalence_map["BEX_TRIANGLE"] = TRI6;
517
518 // TRI7 equivalences
520
521 // HEX8 equivalences
524
525 // HEX20 equivalences
527
528 // HEX27 equivalences
530 // This only supports p==2 IGA:
531 element_equivalence_map["BEX_HEX"] = HEX27;
532
533 // TET4 equivalences
534 element_equivalence_map["TETRA"] = TET4;
535 element_equivalence_map["TETRA4"] = TET4;
536
537 // TET10 equivalences
538 element_equivalence_map["TETRA10"] = TET10;
539 // This only supports p==2 IGA:
540 element_equivalence_map["BEX_TETRA"] = TET10;
541
542 // TET14 (in Exodus 8) equivalence
543 element_equivalence_map["TETRA14"] = TET14;
544
545 // PRISM6 equivalences
548
549 // PRISM15 equivalences
550 element_equivalence_map["WEDGE15"] = PRISM15;
551
552 // PRISM18 equivalences
553 element_equivalence_map["WEDGE18"] = PRISM18;
554 // This only supports p==2 IGA:
555 element_equivalence_map["BEX_WEDGE"] = PRISM18;
556
557 // PRISM20 equivalences
558 element_equivalence_map["WEDGE20"] = PRISM20;
559
560 // PRISM21 equivalences
561 element_equivalence_map["WEDGE21"] = PRISM21;
562
563 // PYRAMID equivalences
565 element_equivalence_map["PYRAMID5"] = PYRAMID5;
566 element_equivalence_map["PYRAMID13"] = PYRAMID13;
567 element_equivalence_map["PYRAMID14"] = PYRAMID14;
568 element_equivalence_map["PYRAMID18"] = PYRAMID18;
569}

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 2580 of file exodusII_io_helper.C.

2581{
2582 // The majority of this function only executes on processor 0, so any functions
2583 // which are collective, like n_active_elem() or n_edge_conds() must be called
2584 // before the processors' execution paths diverge.
2585 libmesh_parallel_only(mesh.comm());
2586
2587 unsigned int n_active_elem = mesh.n_active_elem();
2588 const BoundaryInfo & bi = mesh.get_boundary_info();
2589 num_edge = bi.n_edge_conds();
2590
2591 // We need to know about all processors' subdomains
2592 subdomain_id_type subdomain_id_end = 0;
2593 int c0polyhedron_face_block_id = -1;
2594 auto subdomain_map = build_subdomain_map(mesh,
2595 _add_sides,
2596 subdomain_id_end,
2597 c0polyhedron_face_block_id);
2598
2599 num_elem = n_active_elem;
2600 num_nodes = 0;
2601 num_face = 0;
2602 num_face_blk = 0;
2603
2604 dof_id_type local_num_c0polyhedron_faces = 0;
2605 bool has_c0polyhedron = false;
2606 for (const auto & elem : mesh.active_local_element_ptr_range())
2607 if (elem->type() == C0POLYHEDRON)
2608 {
2609 has_c0polyhedron = true;
2610 local_num_c0polyhedron_faces += elem->n_sides();
2611 }
2612
2613 mesh.comm().sum(local_num_c0polyhedron_faces);
2614 mesh.comm().max(has_c0polyhedron);
2615 if (has_c0polyhedron)
2616 {
2617 num_face = cast_int<int>(local_num_c0polyhedron_faces);
2618 num_face_blk = 1;
2619 }
2620
2621 // If we're adding face elements they'll need copies of their nodes.
2622 // We also have to count of how many nodes (and gaps between nodes!)
2623 // are on each processor, to calculate offsets for any nodal data
2624 // writing later.
2626 if (_add_sides)
2627 {
2628 dof_id_type num_side_elem = 0;
2629 dof_id_type num_local_side_nodes = 0;
2630
2631 for (const auto & elem : mesh.active_local_element_ptr_range())
2632 {
2633 for (auto s : elem->side_index_range())
2634 {
2636 continue;
2637
2638 num_side_elem++;
2639 num_local_side_nodes += elem->nodes_on_side(s).size();
2640 }
2641 }
2642
2643 mesh.comm().sum(num_side_elem);
2644 num_elem += num_side_elem;
2645
2646 mesh.comm().allgather(num_local_side_nodes, _added_side_node_offsets);
2647 const processor_id_type n_proc = mesh.n_processors();
2648 libmesh_assert_equal_to(n_proc, _added_side_node_offsets.size());
2649
2650 for (auto p : make_range(n_proc-1))
2652
2654
2655 dof_id_type n_local_nodes = cast_int<dof_id_type>
2656 (std::distance(mesh.local_nodes_begin(),
2657 mesh.local_nodes_end()));
2658 dof_id_type n_total_nodes = n_local_nodes;
2659 mesh.comm().sum(n_total_nodes);
2660
2661 const dof_id_type max_nn = mesh.max_node_id();
2662 const dof_id_type n_gaps = max_nn - n_total_nodes;
2663 const dof_id_type gaps_per_processor = n_gaps / n_proc;
2664 const dof_id_type remainder_gaps = n_gaps % n_proc;
2665
2666 n_local_nodes = n_local_nodes + // Actual nodes
2667 gaps_per_processor + // Our even share of gaps
2668 (mesh.processor_id() < remainder_gaps); // Leftovers
2669
2670 mesh.comm().allgather(n_local_nodes, _true_node_offsets);
2671 for (auto p : make_range(n_proc-1))
2673 libmesh_assert_equal_to(_true_node_offsets[n_proc-1], mesh.max_node_id());
2674 }
2675
2676 // If _write_as_dimension is nonzero, use it to set num_dim in the Exodus file.
2681 else
2683
2684 if ((_run_only_on_proc0) && (this->processor_id() != 0))
2685 return;
2686
2687 if (!use_discontinuous)
2688 {
2689 // Don't rely on mesh.n_nodes() here. If ReplicatedMesh nodes
2690 // have been deleted without renumbering after, it will be
2691 // incorrect.
2692 num_nodes += cast_int<int>(std::distance(mesh.nodes_begin(),
2693 mesh.nodes_end()));
2694 }
2695 else
2696 {
2697 for (const auto & elem : mesh.active_element_ptr_range())
2698 num_nodes += elem->n_nodes();
2699 }
2700
2701 std::set<boundary_id_type> unique_side_boundaries;
2702 std::vector<boundary_id_type> unique_node_boundaries;
2703
2704 // Build set of unique sideset (+shellface) ids
2705 {
2706 // Start with "side" boundaries (i.e. of 3D elements)
2707 std::vector<boundary_id_type> side_boundaries;
2708 bi.build_side_boundary_ids(side_boundaries);
2709 unique_side_boundaries.insert(side_boundaries.begin(), side_boundaries.end());
2710
2711 // Add shell face boundaries to the list of side boundaries, since ExodusII
2712 // treats these the same way.
2713 std::vector<boundary_id_type> shellface_boundaries;
2714 bi.build_shellface_boundary_ids(shellface_boundaries);
2715 unique_side_boundaries.insert(shellface_boundaries.begin(), shellface_boundaries.end());
2716
2717 // Add any empty-but-named side boundary ids
2718 for (const auto & pr : bi.get_sideset_name_map())
2719 unique_side_boundaries.insert(pr.first);
2720 }
2721
2722 // Build set of unique nodeset ids
2723 bi.build_node_boundary_ids(unique_node_boundaries);
2724 for (const auto & pair : bi.get_nodeset_name_map())
2725 {
2726 const boundary_id_type id = pair.first;
2727
2728 if (std::find(unique_node_boundaries.begin(),
2729 unique_node_boundaries.end(), id)
2730 == unique_node_boundaries.end())
2731 unique_node_boundaries.push_back(id);
2732 }
2733
2734 num_side_sets = cast_int<int>(unique_side_boundaries.size());
2735 num_node_sets = cast_int<int>(unique_node_boundaries.size());
2736
2737 num_elem_blk = cast_int<int>(subdomain_map.size());
2738
2739 if (str_title.size() > MAX_LINE_LENGTH)
2740 {
2741 libMesh::err << "Warning, Exodus files cannot have titles longer than "
2742 << MAX_LINE_LENGTH
2743 << " characters. Your title will be truncated."
2744 << std::endl;
2745 str_title.resize(MAX_LINE_LENGTH);
2746 }
2747
2748 // Edge BCs are handled a bit differently than sidesets and nodesets.
2749 // They are written as separate "edge blocks", and then edge variables
2750 // can be defined on those blocks. That is, they are not written as
2751 // edge sets, since edge sets must refer to edges stored elsewhere.
2752 // We write a separate edge block for each unique boundary id that
2753 // we have.
2754 num_edge_blk = bi.get_edge_boundary_ids().size();
2755
2756 // Check whether the Mesh Elems have an extra_integer called "elemset_code".
2757 // If so, this means that the mesh defines elemsets via the
2758 // extra_integers capability of Elems.
2759 if (mesh.has_elem_integer("elemset_code"))
2760 {
2761 // unsigned int elemset_index =
2762 // mesh.get_elem_integer_index("elemset_code");
2763
2764 // Debugging
2765 // libMesh::out << "Mesh defines an elemset_code at index " << elemset_index << std::endl;
2766
2767 // Store the number of elemsets in the exo file header.
2769 }
2770
2771 // Build an ex_init_params() structure that is to be passed to the
2772 // newer ex_put_init_ext() API. The new API will eventually allow us
2773 // to store edge and face data in the Exodus file.
2774 //
2775 // Notes:
2776 // * We use C++11 zero initialization syntax to make sure that all
2777 // members of the struct (including ones we aren't using) are
2778 // given sensible values.
2779 // * For the "title" field, we manually do a null-terminated string
2780 // copy since std::string does not null-terminate but it does
2781 // return the number of characters successfully copied.
2782 exII::ex_init_params params = {};
2783 params.title[str_title.copy(params.title, MAX_LINE_LENGTH)] = '\0';
2784 params.num_dim = num_dim;
2785 params.num_nodes = num_nodes;
2786 params.num_elem = num_elem;
2787 params.num_elem_blk = num_elem_blk;
2788 params.num_node_sets = num_node_sets;
2789 params.num_side_sets = num_side_sets;
2790 params.num_elem_sets = num_elem_sets;
2791 params.num_edge_blk = num_edge_blk;
2792 params.num_edge = num_edge;
2793 params.num_face_blk = num_face_blk;
2794 params.num_face = num_face;
2795
2796 ex_err = exII::ex_put_init_ext(ex_id, &params);
2797 EX_CHECK_ERR(ex_err, "Error initializing new Exodus file.");
2798}
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:430
unsigned int spatial_dimension() const
Definition mesh_base.C:606
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:482
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::ParallelObject::n_processors(), 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::MeshBase::spatial_dimension(), and libMesh::Parallel::Communicator::sum().

◆ 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 3901 of file exodusII_io_helper.C.

3903{
3904 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3905 return;
3906
3907 // Quick return if there are no element variables to write
3908 if (names.size() == 0)
3909 return;
3910
3911 // Be sure that variables in the file match what we are asking for
3912 if (num_elem_vars > 0)
3913 {
3914 this->check_existing_vars(ELEMENTAL, names, this->elem_var_names);
3915 return;
3916 }
3917
3918 // Quick return if we have already called this function
3920 return;
3921
3922 // Set the flag so we can skip this stuff on subsequent calls to
3923 // initialize_element_variables()
3925
3926 this->write_var_names(ELEMENTAL, names);
3927
3928 // Use the truth table to indicate which subdomain/variable pairs are
3929 // active according to vars_active_subdomains.
3930 std::vector<int> truth_tab(num_elem_blk*num_elem_vars, 0);
3931 for (auto var_num : index_range(vars_active_subdomains))
3932 {
3933 // If the list of active subdomains is empty, it is interpreted as being
3934 // active on *all* subdomains.
3935 std::set<subdomain_id_type> current_set;
3936 if (vars_active_subdomains[var_num].empty())
3937 for (auto block_id : block_ids)
3938 current_set.insert(restrict_int<subdomain_id_type>(block_id));
3939 else
3940 current_set = vars_active_subdomains[var_num];
3941
3942 // Find index into the truth table for each id in current_set.
3943 for (auto block_id : current_set)
3944 {
3945 auto it = std::find(block_ids.begin(), block_ids.end(), block_id);
3946 libmesh_error_msg_if(it == block_ids.end(),
3947 "ExodusII_IO_Helper: block id " << block_id << " not found in block_ids.");
3948
3949 std::size_t block_index =
3950 std::distance(block_ids.begin(), it);
3951
3952 std::size_t truth_tab_index = block_index*num_elem_vars + var_num;
3953 truth_tab[truth_tab_index] = 1;
3954 }
3955 }
3956
3957 ex_err = exII::ex_put_truth_table
3958 (ex_id,
3959 exII::EX_ELEM_BLOCK,
3962 truth_tab.data());
3963 EX_CHECK_ERR(ex_err, "Error writing element truth table.");
3964}
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 3996 of file exodusII_io_helper.C.

3997{
3998 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3999 return;
4000
4001 // Quick return if there are no global variables to write
4002 if (names.size() == 0)
4003 return;
4004
4006 return;
4007
4008 // Be sure that variables in the file match what we are asking for
4009 if (num_global_vars > 0)
4010 {
4011 this->check_existing_vars(GLOBAL, names, this->global_var_names);
4012 return;
4013 }
4014
4016
4017 this->write_var_names(GLOBAL, names);
4018}
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 3968 of file exodusII_io_helper.C.

3969{
3970 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3971 return;
3972
3973 // Quick return if there are no nodal variables to write
3974 if (names.size() == 0)
3975 return;
3976
3977 // Quick return if we have already called this function
3979 return;
3980
3981 // Be sure that variables in the file match what we are asking for
3982 if (num_nodal_vars > 0)
3983 {
3984 this->check_existing_vars(NODAL, names, this->nodal_var_names);
3985 return;
3986 }
3987
3988 // Set the flag so we can skip the rest of this function on subsequent calls.
3990
3991 this->write_var_names(NODAL, names);
3992}
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 600 of file exodusII_io_helper.C.

601{
602 if (verbose) libMesh::out << msg << i << "." << std::endl;
603}

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(), 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::DistributedMesh::DistributedMesh(), 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_unique_id(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), WriteVecAndScalar::setupTests(), libMesh::RBEIMEvaluation::side_gather_bfs(), DistributedMeshTest::testRemoteElemError(), CheckpointIOTest::testSplitter(), libMesh::DistributedMesh::update_parallel_id_counts(), 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 692 of file exodusII_io_helper.C.

693{
694 // Version of Exodus you are using
695 float ex_version = 0.;
696
697 int comp_ws = 0;
698
700 comp_ws = cast_int<int>(sizeof(float));
701
702 // Fall back on double precision when necessary since ExodusII
703 // doesn't seem to support long double
704 else
705 comp_ws = cast_int<int>(std::min(sizeof(Real), sizeof(double)));
706
707 // Word size in bytes of the floating point data as they are stored
708 // in the ExodusII file. "If this argument is 0, the word size of the
709 // floating point data already stored in the file is returned"
710 int io_ws = 0;
711
712 {
713 FPEDisabler disable_fpes;
714 ex_id = exII::ex_open(filename,
715 read_only ? EX_READ : EX_WRITE,
716 &comp_ws,
717 &io_ws,
718 &ex_version);
719 }
720
721 std::string err_msg = std::string("Error opening ExodusII mesh file: ") + std::string(filename);
722 EX_CHECK_ERR(ex_id, err_msg);
723 if (verbose) libMesh::out << "File opened successfully." << std::endl;
724
725 // If we're writing then we'll want to use the specified length;
726 // if we're reading then we'll override this by what's in the file.
727 int max_name_length_to_set = _max_name_length;
728
729 if (read_only)
730 {
731 opened_for_reading = true;
732 elem_node_counts.clear();
733 elem_face_counts.clear();
735
736 // ExodusII reads truncate to 32-char strings by default; we'd
737 // like to support whatever's in the file, so as early as possible
738 // let's find out what that is.
739 int max_name_length = exII::ex_inquire_int(ex_id, exII::EX_INQ_DB_MAX_USED_NAME_LENGTH);
740
741 libmesh_error_msg_if(max_name_length > MAX_LINE_LENGTH,
742 "Unexpected maximum name length of " <<
743 max_name_length << " in file " << filename <<
744 " exceeds expected " << MAX_LINE_LENGTH);
745
746 // I don't think the 32 here should be necessary, but let's make
747 // sure we don't accidentally make things *worse* for anyone.
748 max_name_length_to_set = std::max(max_name_length, 32);
749 }
750 else
751 opened_for_writing = true;
752
753 ex_err = exII::ex_set_max_name_length(ex_id, max_name_length_to_set);
754 EX_CHECK_ERR(ex_err, "Error setting max ExodusII name length.");
755
756 current_filename = std::string(filename);
757}
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 889 of file exodusII_io_helper.C.

890{
891 if (verbose)
892 libMesh::out << "Title: \t" << title.data() << std::endl
893 << "Mesh Dimension: \t" << num_dim << std::endl
894 << "Number of Nodes: \t" << num_nodes << std::endl
895 << "Number of elements: \t" << num_elem << std::endl
896 << "Number of elt blocks: \t" << num_elem_blk << std::endl
897 << "Number of node sets: \t" << num_node_sets << std::endl
898 << "Number of side sets: \t" << num_side_sets << std::endl
899 << "Number of elem sets: \t" << num_elem_sets << std::endl;
900}

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 1091 of file exodusII_io_helper.C.

1092{
1093 for (int i=0; i<num_nodes; i++)
1094 out_stream << "(" << x[i] << ", " << y[i] << ", " << z[i] << ")" << std::endl;
1095}

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(), create(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DistributedMesh::DistributedMesh(), 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::MeshBase::n_constraint_rows(), 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_unique_id(), 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(), 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::testExodusFileMappings(), MeshInputTest::testExodusIGASidesets(), MeshInputTest::testExodusWriteElementDataFromDiscontinuousNodalData(), 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::DistributedMesh::update_parallel_id_counts(), 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 1970 of file exodusII_io_helper.C.

1971{
1972 LOG_SCOPE("read_all_nodesets()", "ExodusII_IO_Helper");
1973
1974 // Figure out how many nodesets there are in the file so we can
1975 // properly resize storage as necessary.
1977 inquire
1978 (*this, exII::EX_INQ_NODE_SETS,
1979 "Error retrieving number of node sets");
1980
1981 // Figure out how many nodes there are in all the nodesets.
1982 int total_nodes_in_all_sets =
1983 inquire
1984 (*this, exII::EX_INQ_NS_NODE_LEN,
1985 "Error retrieving number of nodes in all node sets.");
1986
1987 // Figure out how many distribution factors there are in all the nodesets.
1988 int total_df_in_all_sets =
1989 inquire
1990 (*this, exII::EX_INQ_NS_DF_LEN,
1991 "Error retrieving number of distribution factors in all node sets.");
1992
1993 // If there are no nodesets, there's nothing to read in.
1994 if (num_node_sets == 0)
1995 return;
1996
1997 // Allocate space to read all the nodeset data.
1998 // Use existing class members where possible to avoid shadowing
1999 nodeset_ids.clear(); nodeset_ids.resize(num_node_sets);
2004 node_sets_node_list.clear(); node_sets_node_list.resize(total_nodes_in_all_sets);
2005 node_sets_dist_fact.clear(); node_sets_dist_fact.resize(total_df_in_all_sets);
2006
2007 // Handle single-precision files
2008 MappedInputVector mapped_node_sets_dist_fact(node_sets_dist_fact, _single_precision);
2009
2010 // Build exII::ex_set_spec struct
2011 exII::ex_set_specs set_specs = {};
2012 set_specs.sets_ids = nodeset_ids.data();
2013 set_specs.num_entries_per_set = num_nodes_per_set.data();
2014 set_specs.num_dist_per_set = num_node_df_per_set.data();
2015 set_specs.sets_entry_index = node_sets_node_index.data();
2016 set_specs.sets_dist_index = node_sets_dist_index.data();
2017 set_specs.sets_entry_list = node_sets_node_list.data();
2018 set_specs.sets_extra_list = nullptr;
2019 set_specs.sets_dist_fact = total_df_in_all_sets ? mapped_node_sets_dist_fact.data() : nullptr;
2020
2021 ex_err = exII::ex_get_concat_sets(ex_id, exII::EX_NODE_SET, &set_specs);
2022 EX_CHECK_ERR(ex_err, "Error reading concatenated nodesets");
2023
2024 // Read the nodeset names from file!
2025 char name_buffer[libmesh_max_str_length+1];
2026 for (int i=0; i<num_node_sets; ++i)
2027 {
2028 ex_err = exII::ex_get_name
2029 (ex_id,
2030 exII::EX_NODE_SET,
2031 nodeset_ids[i],
2032 name_buffer);
2033 EX_CHECK_ERR(ex_err, "Error getting node set name.");
2034 id_to_ns_names[nodeset_ids[i]] = name_buffer;
2035 }
2036}
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 794 of file exodusII_io_helper.C.

795{
796 // Read header params from file, storing them in this class's
797 // ExodusHeaderInfo struct. This automatically updates the local
798 // num_dim, num_elem, etc. references.
799 this->header_info = this->read_header();
800
801 // Read the number of timesteps which are present in the file
802 this->read_num_time_steps();
803
804 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_NODAL, &num_nodal_vars);
805 EX_CHECK_ERR(ex_err, "Error reading number of nodal variables.");
806
807 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_BLOCK, &num_elem_vars);
808 EX_CHECK_ERR(ex_err, "Error reading number of elemental variables.");
809
810 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_GLOBAL, &num_global_vars);
811 EX_CHECK_ERR(ex_err, "Error reading number of global variables.");
812
813 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_SIDE_SET, &num_sideset_vars);
814 EX_CHECK_ERR(ex_err, "Error reading number of sideset variables.");
815
816 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_NODE_SET, &num_nodeset_vars);
817 EX_CHECK_ERR(ex_err, "Error reading number of nodeset variables.");
818
819 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_SET, &num_elemset_vars);
820 EX_CHECK_ERR(ex_err, "Error reading number of elemset variables.");
821
822 message("Exodus header info retrieved successfully.");
823}
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 979 of file exodusII_io_helper.C.

980{
981 // If a bex blob exists, we look for Bezier Extraction coefficient
982 // data there.
983
984 // These APIs require newer Exodus than 5.22
985#if EX_API_VERS_NODOT >= 800
986 int n_blobs = exII::ex_inquire_int(ex_id, exII::EX_INQ_BLOB);
987
988 if (n_blobs > 0)
989 {
990 std::vector<exII::ex_blob> blobs(n_blobs);
991 std::vector<std::vector<char>> blob_names(n_blobs);
992 for (auto i : make_range(n_blobs))
993 {
994 blob_names[i].resize(libmesh_max_str_length+1);
995 blobs[i].name = blob_names[i].data();
996 }
997
998 ex_err = exII::ex_get_blobs(ex_id, blobs.data());
999 EX_CHECK_ERR(ex_err, "Error getting blobs.");
1000
1001 bool found_blob = false;
1002 const exII::ex_blob * my_blob = &blobs[0];
1003 for (const auto & blob : blobs)
1004 {
1005 if (std::string("bex_cv_blob") == blob.name)
1006 {
1007 found_blob = true;
1008 my_blob = &blob;
1009 }
1010 }
1011
1012 if (!found_blob)
1013 libmesh_error_msg("Found no bex_cv_blob for bezier elements");
1014
1015 const int n_blob_attr =
1016 exII::ex_get_attribute_count(ex_id, exII::EX_BLOB,
1017 my_blob->id);
1018
1019 std::vector<exII::ex_attribute> attributes(n_blob_attr);
1020 ex_err = exII::ex_get_attribute_param(ex_id, exII::EX_BLOB,
1021 my_blob->id,
1022 attributes.data());
1023 EX_CHECK_ERR(ex_err, "Error getting bex blob attribute parameters.");
1024
1025 int bex_num_dense_cv_blocks = 0;
1026 std::vector<int> bex_dense_cv_info;
1027 for (auto & attr : attributes)
1028 {
1029 if (std::string("bex_dense_cv_info") == attr.name)
1030 {
1031 const std::size_t value_count = attr.value_count;
1032 if (value_count % 2)
1033 libmesh_error_msg("Found odd number of bex_dense_cv_info");
1034
1035 bex_dense_cv_info.resize(value_count);
1036 attr.values = bex_dense_cv_info.data();
1037 exII::ex_get_attribute(ex_id, &attr);
1038
1039 bex_num_dense_cv_blocks = value_count / 2;
1040
1041 libmesh_error_msg_if(bex_num_dense_cv_blocks > 1,
1042 "Found more than 1 dense bex CV block; unsure how to handle that");
1043 }
1044 }
1045
1046 if (bex_dense_cv_info.empty())
1047 libmesh_error_msg("No bex_dense_cv_info found");
1048
1049 int n_blob_vars;
1050 exII::ex_get_variable_param(ex_id, exII::EX_BLOB, &n_blob_vars);
1051 std::vector<char> var_name (libmesh_max_str_length + 1);
1052 for (auto v_id : make_range(1,n_blob_vars+1))
1053 {
1054 ex_err = exII::ex_get_variable_name(ex_id, exII::EX_BLOB, v_id, var_name.data());
1055 EX_CHECK_ERR(ex_err, "Error reading bex blob var name.");
1056
1057 if (std::string("bex_dense_cv_blocks") == var_name.data())
1058 {
1059 std::vector<double> bex_dense_cv_blocks(my_blob->num_entry);
1060
1061 ex_err = exII::ex_get_var(ex_id, 1, exII::EX_BLOB, v_id,
1062 my_blob->id, my_blob->num_entry,
1063 bex_dense_cv_blocks.data());
1064 EX_CHECK_ERR(ex_err, "Error reading bex_dense_cv_blocks.");
1065
1067 bex_dense_constraint_vecs.resize(bex_num_dense_cv_blocks);
1068
1069 std::size_t offset = 0;
1070 for (auto i : IntRange<std::size_t>(0, bex_num_dense_cv_blocks))
1071 {
1072 bex_dense_constraint_vecs[i].resize(bex_dense_cv_info[2*i]);
1073 const int vecsize = bex_dense_cv_info[2*i+1];
1074 for (auto & vec : bex_dense_constraint_vecs[i])
1075 {
1076 vec.resize(vecsize);
1077 std::copy(std::next(bex_dense_cv_blocks.begin(), offset),
1078 std::next(bex_dense_cv_blocks.begin(), offset + vecsize),
1079 vec.begin());
1080 offset += vecsize;
1081 }
1082 }
1083 libmesh_assert(offset == bex_dense_cv_blocks.size());
1084 }
1085 }
1086 }
1087#endif // EX_API_VERS_NODOT >= 800
1088}
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 1099 of file exodusII_io_helper.C.

1100{
1101 if (num_elem_blk)
1102 {
1103 // Read all element block IDs.
1104 block_ids.resize(num_elem_blk);
1105 ex_err = exII::ex_get_ids(ex_id,
1106 exII::EX_ELEM_BLOCK,
1107 block_ids.data());
1108
1109 EX_CHECK_ERR(ex_err, "Error getting block IDs.");
1110 message("All block IDs retrieved successfully.");
1111
1112 char name_buffer[libmesh_max_str_length+1];
1113 for (int i=0; i<num_elem_blk; ++i)
1114 {
1115 ex_err = exII::ex_get_name(ex_id, exII::EX_ELEM_BLOCK,
1116 block_ids[i], name_buffer);
1117 EX_CHECK_ERR(ex_err, "Error getting block name.");
1118 id_to_block_names[block_ids[i]] = name_buffer;
1119 }
1120 message("All block names retrieved successfully.");
1121 }
1122
1123 if (num_edge_blk)
1124 {
1125 // Read all edge block IDs.
1127 ex_err = exII::ex_get_ids(ex_id,
1128 exII::EX_EDGE_BLOCK,
1129 edge_block_ids.data());
1130
1131 EX_CHECK_ERR(ex_err, "Error getting edge block IDs.");
1132 message("All edge block IDs retrieved successfully.");
1133
1134 // Read in edge block names
1135 char name_buffer[libmesh_max_str_length+1];
1136 for (int i=0; i<num_edge_blk; ++i)
1137 {
1138 ex_err = exII::ex_get_name(ex_id, exII::EX_EDGE_BLOCK,
1139 edge_block_ids[i], name_buffer);
1140 EX_CHECK_ERR(ex_err, "Error getting block name.");
1141 id_to_edge_block_names[edge_block_ids[i]] = name_buffer;
1142 }
1143 message("All edge block names retrieved successfully.");
1144 }
1145}
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 1567 of file exodusII_io_helper.C.

1568{
1569 LOG_SCOPE("read_edge_blocks()", "ExodusII_IO_Helper");
1570
1571 // Check for quick return if there are no edge blocks.
1572 if (num_edge_blk == 0)
1573 return;
1574
1575 // Build data structure that we can quickly search for edges
1576 // and then add required BoundaryInfo information. This is a
1577 // map from edge->key() to a list of (elem_id, edge_id) pairs
1578 // for the Edge in question. Since edge->key() is edge orientation
1579 // invariant, this map does not distinguish different orientations
1580 // of the same Edge. Since edge->key() is also not guaranteed to be
1581 // unique (though it is very unlikely for two distinct edges to have
1582 // the same key()), when we later look up an (elem_id, edge_id) pair
1583 // in the edge_map, we need to verify that the edge indeed matches
1584 // the searched edge by doing some further checks.
1585 typedef std::pair<dof_id_type, unsigned int> ElemEdgePair;
1586 std::unordered_map<dof_id_type, std::vector<ElemEdgePair>> edge_map;
1587 std::unique_ptr<Elem> edge_ptr;
1588 for (const auto & elem : mesh.element_ptr_range())
1589 for (auto e : elem->edge_index_range())
1590 {
1591 elem->build_edge_ptr(edge_ptr, e);
1592 dof_id_type edge_key = edge_ptr->key();
1593
1594 // Creates vector if not already there
1595 auto & vec = edge_map[edge_key];
1596 vec.emplace_back(elem->id(), e);
1597
1598 // If edge_ptr is a higher-order Elem (EDGE3 or higher) then also add
1599 // a map entry for the lower-order (EDGE2) element which has matching
1600 // vertices. This allows us to match lower-order edge blocks to edges
1601 // of higher-order 3D elems (e.g. HEX20, TET10) and simplifies the
1602 // definition of edge blocks.
1603 if (edge_ptr->default_order() != FIRST)
1604 {
1605 // Construct a temporary low-order edge so that we can compute its key()
1606 auto low_order_edge =
1608
1609 // Assign node pointers to low-order edge
1610 for (unsigned int v=0; v<edge_ptr->n_vertices(); ++v)
1611 low_order_edge->set_node(v, edge_ptr->node_ptr(v));
1612
1613 // Compute the key for the temporary low-order edge we just built
1614 dof_id_type low_order_edge_key = low_order_edge->key();
1615
1616 // Add this key to the map associated with the same (elem,
1617 // edge) pair as the higher-order edge
1618 auto & low_order_vec = edge_map[low_order_edge_key];
1619 low_order_vec.emplace_back(elem->id(), e);
1620 }
1621 }
1622
1623 // Get reference to the mesh's BoundaryInfo object, as we will be
1624 // adding edges to this below.
1626
1627 for (const auto & edge_block_id : edge_block_ids)
1628 {
1629 // exII::ex_get_block() output parameters. Unlike the other
1630 // "extended" APIs, exII::ex_get_block() does not use a
1631 // parameter struct.
1632 int num_edge_this_blk = 0;
1633 int num_nodes_per_edge = 0;
1634 int num_edges_per_edge = 0;
1635 int num_faces_per_edge = 0;
1636 int num_attr_per_edge = 0;
1637 ex_err = exII::ex_get_block(ex_id,
1638 exII::EX_EDGE_BLOCK,
1639 edge_block_id,
1640 elem_type.data(),
1641 &num_edge_this_blk,
1642 &num_nodes_per_edge,
1643 &num_edges_per_edge, // 0 or -1 for edge blocks
1644 &num_faces_per_edge, // 0 or -1 for edge blocks
1645 &num_attr_per_edge);
1646
1647 EX_CHECK_ERR(ex_err, "Error getting edge block info.");
1648 message("Info retrieved successfully for block: ", edge_block_id);
1649
1650 // Read in the connectivity of the edges of this block,
1651 // watching out for the case where we actually have no
1652 // elements in this block (possible with parallel files)
1653 connect.resize(num_nodes_per_edge * num_edge_this_blk);
1654
1655 if (!connect.empty())
1656 {
1657 ex_err = exII::ex_get_conn(ex_id,
1658 exII::EX_EDGE_BLOCK,
1659 edge_block_id,
1660 connect.data(), // node_conn
1661 nullptr, // elem_edge_conn (unused)
1662 nullptr); // elem_face_conn (unused)
1663
1664 EX_CHECK_ERR(ex_err, "Error reading block connectivity.");
1665 message("Connectivity retrieved successfully for block: ", edge_block_id);
1666
1667 // All edge types have an identity mapping from the corresponding
1668 // Exodus type, so we don't need to bother with mapping ids, but
1669 // we do need to know what kind of elements to build.
1670 const auto & conv = get_conversion(std::string(elem_type.data()));
1671
1672 // Loop over indices in connectivity array, build edge elements,
1673 // look them up in the edge_map.
1674 for (auto [i, sz] = std::make_tuple(0u, connect.size()); i<sz; i+=num_nodes_per_edge)
1675 {
1676 auto edge = Elem::build(conv.libmesh_elem_type());
1677 for (int n=0; n<num_nodes_per_edge; ++n)
1678 {
1679 auto exodus_node_id = this->connect[i+n];
1680 dof_id_type libmesh_node_id = this->get_libmesh_node_id(exodus_node_id);
1681 edge->set_node(n, mesh.node_ptr(libmesh_node_id));
1682 }
1683
1684 // Compute key for the edge Elem we just built.
1685 dof_id_type edge_key = edge->key();
1686
1687 // If this key is not found in the edge_map, which is
1688 // supposed to include every edge in the Mesh, then we
1689 // will throw an error now.
1690 auto & elem_edge_pair_vec =
1691 libmesh_map_find(edge_map, edge_key);
1692
1693 for (const auto & elem_edge_pair : elem_edge_pair_vec)
1694 {
1695 // We only want to match edges which have the same
1696 // nodes (possibly with different orientation) to the one in the
1697 // Exodus file, otherwise we ignore this elem_edge_pair.
1698 //
1699 // Note: this also handles the situation where two
1700 // edges have the same key (hash collision) as then
1701 // this check avoids a false positive.
1702
1703 // Build edge indicated by elem_edge_pair
1704 mesh.elem_ptr(elem_edge_pair.first)->
1705 build_edge_ptr(edge_ptr, elem_edge_pair.second);
1706
1707 // Determine whether this candidate edge is a "real" match,
1708 // i.e. has the same nodes with a possibly different
1709 // orientation. Note that here we only check that
1710 // the vertices match regardless of how many nodes
1711 // the edge has, which allows us to match a
1712 // lower-order edge to a higher-order Elem.
1713 bool is_match =
1714 ((edge_ptr->node_id(0) == edge->node_id(0)) && (edge_ptr->node_id(1) == edge->node_id(1))) ||
1715 ((edge_ptr->node_id(0) == edge->node_id(1)) && (edge_ptr->node_id(1) == edge->node_id(0)));
1716
1717 if (is_match)
1718 {
1719 // Add this (elem, edge, id) combo to the BoundaryInfo object.
1720 bi.add_edge(elem_edge_pair.first,
1721 elem_edge_pair.second,
1722 edge_block_id);
1723 }
1724 } // end loop over elem_edge_pairs
1725 } // end loop over connectivity array
1726
1727 // Set edgeset name in the BoundaryInfo object.
1728 bi.edgeset_name(edge_block_id) = id_to_edge_block_names[edge_block_id];
1729 } // end if !connect.empty()
1730 } // end for edge_block_id : edge_block_ids
1731}
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:3099
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(), connect, edge_block_ids, 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(), 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 1322 of file exodusII_io_helper.C.

1323{
1324 LOG_SCOPE("read_elem_in_block()", "ExodusII_IO_Helper");
1325
1326 libmesh_assert_less (block, block_ids.size());
1327 elem_node_counts.clear();
1328 elem_face_counts.clear();
1329
1330 // Unlike the other "extended" APIs, this one does not use a parameter struct.
1331 int num_edges_per_elem = 0;
1332 int num_faces_per_elem = 0;
1333 int num_node_data_per_elem = 0;
1334 ex_err = exII::ex_get_block(ex_id,
1335 exII::EX_ELEM_BLOCK,
1336 block_ids[block],
1337 elem_type.data(),
1339 &num_node_data_per_elem,
1340 &num_edges_per_elem, // 0 or -1 if no "extended" block info
1341 &num_faces_per_elem, // 0 or -1 if no "extended" block info
1342 &num_attr);
1343
1344 EX_CHECK_ERR(ex_err, "Error getting block info.");
1345 message("Info retrieved successfully for block: ", block);
1346
1347 // Nemesis uses "Empty" as the element type for blocks with no
1348 // elements on the current processor. There is no element conversion
1349 // for that sentinel type, nor is one needed for an empty block.
1350 const bool is_bezier = is_bezier_elem(elem_type.data());
1351 const Conversion * conversion = nullptr;
1352 if (num_elem_this_blk || is_bezier)
1353 conversion = &get_conversion(std::string(elem_type.data()));
1354
1355 const bool is_c0polygon =
1356 conversion && conversion->libmesh_elem_type() == C0POLYGON;
1357 const bool is_c0polyhedron =
1358 conversion && conversion->libmesh_elem_type() == C0POLYHEDRON;
1359
1360 // Warn or error when we don't currently support reading blocks with extended info.
1361 // Note: the docs say -1 will be returned for this but I found that it was
1362 // actually 0, so not sure which it will be in general.
1363 if (is_c0polyhedron && !(num_edges_per_elem == 0) && !(num_edges_per_elem == -1))
1364 libmesh_error_msg("Error: Exodus NFACED element blocks with edge "
1365 "connectivity are not currently supported.");
1366 else if (!(num_edges_per_elem == 0) && !(num_edges_per_elem == -1))
1367 libmesh_warning("Exodus files with extended edge connectivity not currently supported.");
1368 if (!is_c0polyhedron && !(num_faces_per_elem == 0) && !(num_faces_per_elem == -1))
1369 libmesh_warning("Exodus files with extended face connectivity not currently supported.");
1370
1371 // If we have a Bezier element here, then we've packed constraint
1372 // vector connectivity at the end of the nodal connectivity, and
1373 // num_nodes_per_elem reflected both.
1374 if (is_bezier)
1375 {
1376 libmesh_assert(conversion);
1377 num_nodes_per_elem = conversion->n_nodes;
1378 }
1379 else if (is_c0polygon)
1380 {
1382
1383 if (!elem_node_counts.empty())
1384 {
1385 ex_err = exII::ex_get_entity_count_per_polyhedra
1386 (ex_id,
1387 exII::EX_ELEM_BLOCK,
1388 block_ids[block],
1389 elem_node_counts.data());
1390 EX_CHECK_ERR(ex_err, "Error reading polygon node counts");
1391 }
1392
1393 int counted_nodes = 0;
1394 for (const auto count : elem_node_counts)
1395 counted_nodes += count;
1396
1397 libmesh_error_msg_if(counted_nodes != num_node_data_per_elem,
1398 "Error: Exodus NSIDED block "
1399 << block_ids[block]
1400 << " says it has " << num_node_data_per_elem
1401 << " total node entries, but its per-element "
1402 << "node counts sum to " << counted_nodes << ".");
1403
1405 }
1406 else if (is_c0polyhedron)
1407 {
1408 if (c0polyhedron_face_connect.empty())
1409 this->read_face_blocks();
1410
1412
1413 if (!elem_face_counts.empty())
1414 {
1415 ex_err = exII::ex_get_entity_count_per_polyhedra
1416 (ex_id,
1417 exII::EX_ELEM_BLOCK,
1418 block_ids[block],
1419 elem_face_counts.data());
1420 EX_CHECK_ERR(ex_err, "Error reading polyhedron face counts");
1421 }
1422
1423 int counted_faces = 0;
1424 for (const auto count : elem_face_counts)
1425 counted_faces += count;
1426
1427 libmesh_error_msg_if(counted_faces != num_faces_per_elem,
1428 "Error: Exodus NFACED block "
1429 << block_ids[block]
1430 << " says it has " << num_faces_per_elem
1431 << " total face entries, but its per-element "
1432 << "face counts sum to " << counted_faces << ".");
1433
1435 }
1436 else
1437 num_nodes_per_elem = num_node_data_per_elem;
1438
1439 if (verbose)
1440 {
1441 libMesh::out << "Read a block of " << num_elem_this_blk
1442 << " " << elem_type.data() << "(s)";
1443 if (is_c0polygon)
1444 libMesh::out << " having " << num_node_data_per_elem
1445 << " total node entries.";
1446 else if (is_c0polyhedron)
1447 libMesh::out << " having " << num_faces_per_elem
1448 << " total face entries.";
1449 else
1450 libMesh::out << " having " << num_nodes_per_elem
1451 << " nodes per element.";
1452 libMesh::out << std::endl;
1453 }
1454
1455 // Read in the connectivity of the elements of this block,
1456 // watching out for the case where we actually have no
1457 // elements in this block (possible with parallel files)
1458 connect.resize(is_c0polygon ?
1459 num_node_data_per_elem :
1460 is_c0polyhedron ?
1461 num_faces_per_elem :
1462 num_node_data_per_elem*num_elem_this_blk);
1463
1464 if (!connect.empty())
1465 {
1466 ex_err = exII::ex_get_conn(ex_id,
1467 exII::EX_ELEM_BLOCK,
1468 block_ids[block],
1469 is_c0polyhedron ? nullptr : connect.data(),
1470 nullptr, // elem_edge_conn (unused)
1471 is_c0polyhedron ? connect.data() : nullptr);
1472
1473 EX_CHECK_ERR(ex_err, "Error reading block connectivity.");
1474 message("Connectivity retrieved successfully for block: ", block);
1475 }
1476
1477 // If we had any attributes for this block, check to see if some of
1478 // them were Bezier-extension attributes.
1479
1480 // num_attr above is zero, not actually the number of block attributes?
1481 // ex_get_attr_param *also* gives me zero? Really, Exodus?
1482#if EX_API_VERS_NODOT >= 800
1483 int real_n_attr = exII::ex_get_attribute_count(ex_id, exII::EX_ELEM_BLOCK, block_ids[block]);
1484 EX_CHECK_ERR(real_n_attr, "Error getting number of element block attributes.");
1485
1486 if (real_n_attr > 0)
1487 {
1488 std::vector<exII::ex_attribute> attributes(real_n_attr);
1489
1490 ex_err = exII::ex_get_attribute_param(ex_id, exII::EX_ELEM_BLOCK, block_ids[block], attributes.data());
1491 EX_CHECK_ERR(ex_err, "Error getting element block attribute parameters.");
1492
1493 ex_err = exII::ex_get_attributes(ex_id, real_n_attr, attributes.data());
1494 EX_CHECK_ERR(ex_err, "Error getting element block attribute values.");
1495
1496 for (auto attr : attributes)
1497 {
1498 if (std::string("bex_elem_degrees") == attr.name)
1499 {
1500 if (attr.type != exII::EX_INTEGER)
1501 libmesh_error_msg("Found non-integer bex_elem_degrees");
1502
1503 if (attr.value_count > 3)
1504 libmesh_error_msg("Looking for at most 3 bex_elem_degrees; found " << attr.value_count);
1505
1506 libmesh_assert(is_bezier);
1507
1508 std::vector<int> bex_elem_degrees(3); // max dim
1509
1510 const int * as_int = static_cast<int *>(attr.values);
1511 std::copy(as_int, as_int+attr.value_count, bex_elem_degrees.begin());
1512
1513
1514 // Right now Bezier extraction elements aren't possible
1515 // for p>2 and aren't useful for p<2, and we don't
1516 // support anisotropic p...
1517#ifndef NDEBUG
1518 libmesh_assert(conversion);
1519 for (auto d : IntRange<int>(0, conversion->dim))
1520 libmesh_assert_equal_to(bex_elem_degrees[d], 2);
1521#endif
1522 }
1523 // ex_get_attributes did a values=calloc(); free() is our job.
1524 if (attr.values)
1525 free(attr.values);
1526 }
1527 }
1528
1529 if (is_bezier)
1530 {
1531 // We'd better have the number of cvs we expect
1532 if( num_node_data_per_elem > num_nodes_per_elem )
1533 bex_num_elem_cvs = num_node_data_per_elem / 2;
1534 else
1536 libmesh_assert_greater_equal(bex_num_elem_cvs, 0);
1537
1538 // The old connect vector is currently a mix of the expected
1539 // connectivity and any Bezier extraction connectivity;
1540 // disentangle that, if necessary.
1542 if (num_node_data_per_elem > num_nodes_per_elem)
1543 {
1544 std::vector<int> old_connect(bex_num_elem_cvs * num_elem_this_blk);
1545 old_connect.swap(connect);
1546 auto src = old_connect.data();
1547 auto dst = connect.data();
1548 for (auto e : IntRange<std::size_t>(0, num_elem_this_blk))
1549 {
1550 std::copy(src, src + bex_num_elem_cvs, dst);
1551 src += bex_num_elem_cvs;
1552 dst += bex_num_elem_cvs;
1553
1554 bex_cv_conn[e].resize(bex_num_elem_cvs);
1555 std::copy(src, src + bex_num_elem_cvs,
1556 bex_cv_conn[e].begin());
1557 src += bex_num_elem_cvs;
1558 }
1559 }
1560 }
1561
1562#endif // EX_API_VERS_NODOT >= 800
1563}
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 1735 of file exodusII_io_helper.C.

1736{
1737 elem_num_map.resize(num_elem);
1738
1739 // Note: we cannot use the exII::ex_get_num_map() here because it
1740 // (apparently) does not behave like ex_get_elem_num_map() when
1741 // there is no elem number map in the file: it throws an error
1742 // instead of returning a default identity array (1,2,3,...).
1743 ex_err = exII::ex_get_elem_num_map
1744 (ex_id, elem_num_map.empty() ? nullptr : elem_num_map.data());
1745
1746 EX_CHECK_ERR(ex_err, "Error retrieving element number map.");
1747 message("Element numbering map retrieved successfully.");
1748
1749 if (num_elem)
1750 {
1751 // The elem_num_map may contain ids larger than num_elem. In
1752 // other words, the elem_num_map is not necessarily just a
1753 // permutation of the "trivial" 1,2,3,... mapping, it can
1754 // contain effectively "any" numbers. Therefore, to get
1755 // "_end_elem_id", we need to check what the max entry in the
1756 // elem_num_map is.
1757 auto it = std::max_element(elem_num_map.begin(), elem_num_map.end());
1758 _end_elem_id = *it;
1759 }
1760 else
1761 _end_elem_id = 0;
1762
1763 if (verbose)
1764 {
1765 libMesh::out << "[" << this->processor_id() << "] elem_num_map[i] = ";
1766 for (unsigned int i=0; i<static_cast<unsigned int>(std::min(10, num_elem-1)); ++i)
1767 libMesh::out << elem_num_map[i] << ", ";
1768 libMesh::out << "... " << elem_num_map.back() << std::endl;
1769 }
1770}

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 2329 of file exodusII_io_helper.C.

2332{
2333 LOG_SCOPE("read_elemental_var_values()", "ExodusII_IO_Helper");
2334
2336
2337 // See if we can find the variable we are looking for
2338 unsigned int var_index = 0;
2339 bool found = false;
2340
2341 // Do a linear search for elem_var_name in elemental_var_names
2342 for (; var_index != elem_var_names.size(); ++var_index)
2343 if (elem_var_names[var_index] == elemental_var_name)
2344 {
2345 found = true;
2346 break;
2347 }
2348
2349 if (!found)
2350 {
2351 libMesh::err << "Available variables: " << std::endl;
2352 for (const auto & var_name : elem_var_names)
2353 libMesh::err << var_name << std::endl;
2354
2355 libmesh_error_msg("Unable to locate variable named: " << elemental_var_name);
2356 }
2357
2358 // Sequential index which we can use to look up the element ID in the elem_num_map.
2359 unsigned ex_el_num = 0;
2360
2361 // Element variable truth table
2362 std::vector<int> var_table(block_ids.size() * elem_var_names.size());
2363 exII::ex_get_truth_table(ex_id, exII::EX_ELEM_BLOCK, block_ids.size(), elem_var_names.size(), var_table.data());
2364
2365 for (unsigned i=0; i<static_cast<unsigned>(num_elem_blk); i++)
2366 {
2367 ex_err = exII::ex_get_block(ex_id,
2368 exII::EX_ELEM_BLOCK,
2369 block_ids[i],
2370 /*elem_type=*/nullptr,
2372 /*num_nodes_per_entry=*/nullptr,
2373 /*num_edges_per_entry=*/nullptr,
2374 /*num_faces_per_entry=*/nullptr,
2375 /*num_attr=*/nullptr);
2376 EX_CHECK_ERR(ex_err, "Error getting number of elements in block.");
2377
2378 // If the current variable isn't active on this subdomain, advance
2379 // the index by the number of elements on this block and go to the
2380 // next loop iteration.
2381 if (!var_table[elem_var_names.size()*i + var_index])
2382 {
2383 ex_el_num += num_elem_this_blk;
2384 continue;
2385 }
2386
2387 std::vector<Real> block_elem_var_values(num_elem_this_blk);
2388
2389 ex_err = exII::ex_get_var
2390 (ex_id,
2391 time_step,
2392 exII::EX_ELEM_BLOCK,
2393 var_index+1,
2394 block_ids[i],
2396 MappedInputVector(block_elem_var_values, _single_precision).data());
2397 EX_CHECK_ERR(ex_err, "Error getting elemental values.");
2398
2399 for (unsigned j=0; j<static_cast<unsigned>(num_elem_this_blk); j++)
2400 {
2401 // Determine the libmesh id of the element with zero-based
2402 // index "ex_el_num". This function expects a one-based
2403 // index, so we add 1 to ex_el_num when we pass it in.
2404 auto libmesh_elem_id =
2405 this->get_libmesh_elem_id(ex_el_num + 1);
2406
2407 // Store the elemental value in the map.
2408 elem_var_value_map[libmesh_elem_id] = block_elem_var_values[j];
2409
2410 // Go to the next sequential element ID.
2411 ex_el_num++;
2412 }
2413 }
2414}
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 1925 of file exodusII_io_helper.C.

1926{
1927 LOG_SCOPE("read_elemset()", "ExodusII_IO_Helper");
1928
1929 libmesh_assert_less (id, elemset_ids.size());
1930 libmesh_assert_less (id, num_elems_per_set.size());
1931 libmesh_assert_less (id, num_elem_df_per_set.size());
1932 libmesh_assert_less_equal (offset, elemset_list.size());
1933
1934 ex_err = exII::ex_get_set_param(ex_id,
1935 exII::EX_ELEM_SET,
1936 elemset_ids[id],
1937 &num_elems_per_set[id],
1938 &num_elem_df_per_set[id]);
1939 EX_CHECK_ERR(ex_err, "Error retrieving elemset parameters.");
1940 message("Parameters retrieved successfully for elemset: ", id);
1941
1942
1943 // It's OK for offset==elemset_list.size() as long as num_elems_per_set[id]==0
1944 // because in that case we don't actually read anything...
1945 #ifdef DEBUG
1946 if (static_cast<unsigned int>(offset) == elemset_list.size())
1947 libmesh_assert_equal_to (num_elems_per_set[id], 0);
1948 #endif
1949
1950 // Don't call ex_get_set() unless there are actually elems there to get.
1951 // Exodus prints an annoying warning in DEBUG mode otherwise...
1952 if (num_elems_per_set[id] > 0)
1953 {
1954 ex_err = exII::ex_get_set(ex_id,
1955 exII::EX_ELEM_SET,
1956 elemset_ids[id],
1957 &elemset_list[offset],
1958 /*set_extra_list=*/nullptr);
1959 EX_CHECK_ERR(ex_err, "Error retrieving elemset data.");
1960 message("Data retrieved successfully for elemset: ", id);
1961
1962 // Create vector containing elemset ids for each element in the set
1963 for (int i=0; i<num_elems_per_set[id]; i++)
1964 elemset_id_list[i+offset] = elemset_ids[id];
1965 }
1966}
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 4701 of file exodusII_io_helper.C.

4706{
4707 LOG_SCOPE("read_elemset_data()", "ExodusII_IO_Helper");
4708
4709 // This reads the elemset variable names into the local
4710 // elemset_var_names data structure.
4711 this->read_var_names(ELEMSET);
4712
4713 // Debugging
4714 // libMesh::out << "elmeset variable names:" << std::endl;
4715 // for (const auto & name : elemset_var_names)
4716 // libMesh::out << name << " ";
4717 // libMesh::out << std::endl;
4718
4719 if (num_elemset_vars)
4720 {
4721 // Debugging
4722 // std::cout << "Reading " << num_elem_sets
4723 // << " elemsets and " << num_elemset_vars
4724 // << " elemset variables." << std::endl;
4725
4726 // Read the elemset data truth table.
4727 std::vector<int> elemset_var_tab(num_elem_sets * num_elemset_vars);
4728 exII::ex_get_truth_table(ex_id,
4729 exII::EX_ELEM_SET, // exII::ex_entity_type
4732 elemset_var_tab.data());
4733 EX_CHECK_ERR(ex_err, "Error reading elemset variable truth table.");
4734
4735 // Debugging
4736 // libMesh::out << "Elemset variable truth table:" << std::endl;
4737 // for (const auto & val : elemset_var_tab)
4738 // libMesh::out << val << " ";
4739 // libMesh::out << std::endl;
4740
4741 // Debugging
4742 // for (auto i : make_range(num_elem_sets))
4743 // {
4744 // for (auto j : make_range(num_elemset_vars))
4745 // libMesh::out << elemset_var_tab[num_elemset_vars*i + j] << " ";
4746 // libMesh::out << std::endl;
4747 // }
4748
4749 // Set up/allocate space in incoming data structures. All vectors are
4750 // num_elemset_vars in length.
4751 var_names = elemset_var_names;
4752 elemset_ids_in.resize(num_elemset_vars);
4753 elemset_vals.resize(num_elemset_vars);
4754
4755 // Read the elemset data
4756 int offset=0;
4757 for (int es=0; es<num_elem_sets; ++es)
4758 {
4759 offset += (es > 0 ? num_elems_per_set[es-1] : 0);
4760 for (int var=0; var<num_elemset_vars; ++var)
4761 {
4762 int is_present = elemset_var_tab[num_elemset_vars*es + var];
4763
4764 if (is_present)
4765 {
4766 // Debugging
4767 // libMesh::out << "Variable " << var << " is present on elemset " << es << std::endl;
4768
4769 // Record the fact that this variable is defined on this elemset.
4770 elemset_ids_in[var].insert(elemset_ids[es]);
4771
4772 // Note: the assumption here is that a previous call
4773 // to this->read_elemset_info() has already set the
4774 // values of num_elems_per_set, so we just use those values here.
4775 std::vector<Real> elemset_var_vals(num_elems_per_set[es]);
4776 ex_err = exII::ex_get_var
4777 (ex_id,
4778 timestep,
4779 exII::EX_ELEM_SET, // exII::ex_entity_type
4780 var + 1, // 1-based sideset variable index!
4781 elemset_ids[es],
4783 MappedInputVector(elemset_var_vals, _single_precision).data());
4784 EX_CHECK_ERR(ex_err, "Error reading elemset variable.");
4785
4786 for (int i=0; i<num_elems_per_set[es]; ++i)
4787 {
4788 dof_id_type exodus_elem_id = elemset_list[i + offset];
4789
4790 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4791 // but it apparently is never set up, so just
4792 // subtract 1 from the Exodus elem id.
4793 dof_id_type converted_elem_id = exodus_elem_id - 1;
4794
4795 // Make key based on the elem and set ids
4796 auto key = std::make_pair(converted_elem_id,
4797 static_cast<elemset_id_type>(elemset_ids[es]));
4798
4799 // Store value in the map
4800 elemset_vals[var].emplace(key, elemset_var_vals[i]);
4801 } // end for (i)
4802 } // end if (present)
4803 } // end for (var)
4804 } // end for (es)
4805 } // end if (num_elemset_vars)
4806}
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 1838 of file exodusII_io_helper.C.

1839{
1840 elemset_ids.resize(num_elem_sets);
1841 if (num_elem_sets > 0)
1842 {
1843 ex_err = exII::ex_get_ids(ex_id,
1844 exII::EX_ELEM_SET,
1845 elemset_ids.data());
1846 EX_CHECK_ERR(ex_err, "Error retrieving elemset information.");
1847 message("All elemset information retrieved successfully.");
1848
1849 // Resize appropriate data structures -- only do this once outside the loop
1852
1853 // Inquire about the length of the concatenated elemset list
1855 inquire(*this, exII::EX_INQ_ELS_LEN,
1856 "Error retrieving length of the concatenated elem sets element list!");
1857
1860
1861 // Debugging
1862 // libMesh::out << "num_elem_all_elemsets = " << num_elem_all_elemsets << std::endl;
1863 }
1864
1865 char name_buffer[libmesh_max_str_length+1];
1866 for (int i=0; i<num_elem_sets; ++i)
1867 {
1868 ex_err = exII::ex_get_name(ex_id, exII::EX_ELEM_SET,
1869 elemset_ids[i], name_buffer);
1870 EX_CHECK_ERR(ex_err, "Error getting node set name.");
1871 id_to_elemset_names[elemset_ids[i]] = name_buffer;
1872 }
1873 message("All elem set names retrieved successfully.");
1874}
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 1202 of file exodusII_io_helper.C.

1203{
1204 LOG_SCOPE("read_face_blocks()", "ExodusII_IO_Helper");
1205
1206 if (!c0polyhedron_face_connect.empty())
1207 return;
1208
1209 libmesh_error_msg_if(num_face_blk == 0,
1210 "Error: Exodus NFACED element block found, "
1211 "but the file has no face blocks.");
1212
1213 std::vector<int> face_block_ids(num_face_blk);
1214 ex_err = exII::ex_get_ids(ex_id,
1215 exII::EX_FACE_BLOCK,
1216 face_block_ids.data());
1217 EX_CHECK_ERR(ex_err, "Error getting face block IDs.");
1218
1221
1222 for (auto block : index_range(face_block_ids))
1223 {
1224 std::vector<char> face_type(libmesh_max_str_length+1);
1225 int num_face_this_blk = 0;
1226 int num_node_data_this_blk = 0;
1227 int num_edges_per_face = 0;
1228 int num_faces_per_face = 0;
1229 int num_attr_face = 0;
1230
1231 ex_err = exII::ex_get_block(ex_id,
1232 exII::EX_FACE_BLOCK,
1233 face_block_ids[block],
1234 face_type.data(),
1235 &num_face_this_blk,
1236 &num_node_data_this_blk,
1237 &num_edges_per_face,
1238 &num_faces_per_face,
1239 &num_attr_face);
1240 EX_CHECK_ERR(ex_err, "Error getting face block info.");
1241
1242 const auto & conv = get_conversion(std::string(face_type.data()));
1243 libmesh_error_msg_if(conv.libmesh_elem_type() != C0POLYGON,
1244 "Error: NFACED polyhedron input currently expects "
1245 "NSIDED face blocks, but face block "
1246 << face_block_ids[block] << " has Exodus type "
1247 << face_type.data() << ".");
1248
1249 libmesh_error_msg_if
1250 (!(num_edges_per_face == 0) && !(num_edges_per_face == -1),
1251 "Error: Exodus NSIDED face block "
1252 << face_block_ids[block]
1253 << " has edge connectivity, which NFACED polyhedron input "
1254 << "does not currently support.");
1255 libmesh_error_msg_if
1256 (!(num_faces_per_face == 0) && !(num_faces_per_face == -1),
1257 "Error: Exodus NSIDED face block "
1258 << face_block_ids[block]
1259 << " has face-in-face connectivity, which NFACED polyhedron "
1260 << "input does not currently support.");
1261
1262 std::vector<int> face_node_counts(num_face_this_blk);
1263 if (!face_node_counts.empty())
1264 {
1265 ex_err = exII::ex_get_entity_count_per_polyhedra
1266 (ex_id,
1267 exII::EX_FACE_BLOCK,
1268 face_block_ids[block],
1269 face_node_counts.data());
1270 EX_CHECK_ERR(ex_err, "Error reading polyhedron face node counts");
1271 }
1272
1273 int counted_nodes = 0;
1274 for (const auto count : face_node_counts)
1275 counted_nodes += count;
1276
1277 libmesh_error_msg_if(counted_nodes != num_node_data_this_blk,
1278 "Error: Exodus NSIDED face block "
1279 << face_block_ids[block]
1280 << " says it has " << num_node_data_this_blk
1281 << " total node entries, but its per-face "
1282 << "node counts sum to " << counted_nodes << ".");
1283
1284 std::vector<int> face_connect(num_node_data_this_blk);
1285 if (!face_connect.empty())
1286 {
1287 ex_err = exII::ex_get_conn(ex_id,
1288 exII::EX_FACE_BLOCK,
1289 face_block_ids[block],
1290 face_connect.data(),
1291 nullptr,
1292 nullptr);
1293 EX_CHECK_ERR(ex_err, "Error reading polyhedron face connectivity.");
1294 }
1295
1296 std::size_t offset = 0;
1297 for (const auto count : face_node_counts)
1298 {
1299 libmesh_error_msg_if(count < 3,
1300 "Error: Exodus NSIDED face block "
1301 << face_block_ids[block]
1302 << " has a face with only "
1303 << count << " nodes.");
1304
1305 c0polyhedron_face_connect.emplace_back
1306 (face_connect.begin() + offset,
1307 face_connect.begin() + offset + count);
1308 offset += count;
1309 }
1310 }
1311
1312 libmesh_error_msg_if(c0polyhedron_face_connect.size() !=
1313 cast_int<std::size_t>(num_face),
1314 "Error: Exodus file says it has "
1315 << num_face << " faces, but its face blocks contain "
1316 << c0polyhedron_face_connect.size() << " faces.");
1317}

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 5318 of file exodusII_io_helper.C.

5319{
5320 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5321 return;
5322
5323 values.clear();
5324 values.resize(num_global_vars);
5325 ex_err = exII::ex_get_var
5326 (ex_id,
5327 timestep,
5328 exII::EX_GLOBAL,
5329 1, // var_index
5330 1, // obj_id
5332 MappedInputVector(values, _single_precision).data());
5333
5334 EX_CHECK_ERR(ex_err, "Error reading global values.");
5335}

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 762 of file exodusII_io_helper.C.

763{
764 // Read init params using newer API that reads into a struct. For
765 // backwards compatibility, assign local member values from struct
766 // afterwards. Note: using the new API allows us to automatically
767 // read edge and face block/set information if it's present in the
768 // file.
769 exII::ex_init_params params = {};
770 int err_flag = exII::ex_get_init_ext(ex_id, &params);
771 EX_CHECK_ERR(err_flag, "Error retrieving header info.");
772
773 // Extract required data into our struct
775 h.title.assign(params.title, params.title + MAX_LINE_LENGTH);
776 h.num_dim = params.num_dim;
777 h.num_nodes = params.num_nodes;
778 h.num_elem = params.num_elem;
779 h.num_elem_blk = params.num_elem_blk;
780 h.num_node_sets = params.num_node_sets;
781 h.num_side_sets = params.num_side_sets;
782 h.num_elem_sets = params.num_elem_sets;
783 h.num_edge_blk = params.num_edge_blk;
784 h.num_edge = params.num_edge;
785 h.num_face_blk = params.num_face_blk;
786 h.num_face = params.num_face;
787
788 // And return it
789 return h;
790}
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 2104 of file exodusII_io_helper.C.

2105{
2106 LOG_SCOPE("read_nodal_var_values()", "ExodusII_IO_Helper");
2107
2108 // Read the nodal variable names from file, so we can see if we have the one we're looking for
2109 this->read_var_names(NODAL);
2110
2111 // See if we can find the variable we are looking for
2112 unsigned int var_index = 0;
2113 bool found = false;
2114
2115 // Do a linear search for nodal_var_name in nodal_var_names
2116 for (; var_index<nodal_var_names.size(); ++var_index)
2117 {
2118 found = (nodal_var_names[var_index] == nodal_var_name);
2119 if (found)
2120 break;
2121 }
2122
2123 if (!found)
2124 {
2125 libMesh::err << "Available variables: " << std::endl;
2126 for (const auto & var_name : nodal_var_names)
2127 libMesh::err << var_name << std::endl;
2128
2129 libmesh_error_msg("Unable to locate variable named: " << nodal_var_name);
2130 }
2131
2132 // Clear out any previously read nodal variable values
2133 this->nodal_var_values.clear();
2134
2135 std::vector<Real> unmapped_nodal_var_values(num_nodes);
2136
2137 // Call the Exodus API to read the nodal variable values
2138 ex_err = exII::ex_get_var
2139 (ex_id,
2140 time_step,
2141 exII::EX_NODAL,
2142 var_index+1,
2143 1, // exII::ex_entity_id, not sure exactly what this is but in the ex_get_nodal_var.c shim, they pass 1
2144 num_nodes,
2145 MappedInputVector(unmapped_nodal_var_values, _single_precision).data());
2146 EX_CHECK_ERR(ex_err, "Error reading nodal variable values!");
2147
2148 for (auto i : make_range(num_nodes))
2149 {
2150 // Determine the libmesh node id implied by "i". The
2151 // get_libmesh_node_id() helper function expects a 1-based
2152 // Exodus node id, so we construct the "implied" Exodus node id
2153 // from "i" by adding 1.
2154 //
2155 // If the user has set the "set_unique_ids_from_maps" flag to
2156 // true, then calling get_libmesh_node_id(i+1) will just return
2157 // i, otherwise it will determine the value (with error
2158 // checking) using this->node_num_map.
2159 auto libmesh_node_id = this->get_libmesh_node_id(/*exodus_node_id=*/i+1);
2160
2161 // Store the nodal value in the map.
2162 this->nodal_var_values[libmesh_node_id] = unmapped_nodal_var_values[i];
2163 }
2164}
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 955 of file exodusII_io_helper.C.

956{
957 node_num_map.resize(num_nodes);
958
959 // Note: we cannot use the exII::ex_get_num_map() here because it
960 // (apparently) does not behave like ex_get_node_num_map() when
961 // there is no node number map in the file: it throws an error
962 // instead of returning a default identity array (1,2,3,...).
963 ex_err = exII::ex_get_node_num_map
964 (ex_id, node_num_map.empty() ? nullptr : node_num_map.data());
965
966 EX_CHECK_ERR(ex_err, "Error retrieving nodal number map.");
967 message("Nodal numbering map retrieved successfully.");
968
969 if (verbose)
970 {
971 libMesh::out << "[" << this->processor_id() << "] node_num_map[i] = ";
972 for (unsigned int i=0; i<static_cast<unsigned int>(std::min(10, num_nodes-1)); ++i)
973 libMesh::out << node_num_map[i] << ", ";
974 libMesh::out << "... " << node_num_map.back() << std::endl;
975 }
976}

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 904 of file exodusII_io_helper.C.

905{
906 LOG_SCOPE("read_nodes()", "ExodusII_IO_Helper");
907
908 x.resize(num_nodes);
909 y.resize(num_nodes);
910 z.resize(num_nodes);
911
912 if (num_nodes)
913 {
914 ex_err = exII::ex_get_coord
915 (ex_id,
916 MappedInputVector(x, _single_precision).data(),
917 MappedInputVector(y, _single_precision).data(),
918 MappedInputVector(z, _single_precision).data());
919
920 EX_CHECK_ERR(ex_err, "Error retrieving nodal data.");
921 message("Nodal data retrieved successfully.");
922 }
923
924 // If a nodal attribute bex_weight exists, we get spline weights
925 // from it
926 int n_nodal_attr = 0;
927 ex_err = exII::ex_get_attr_param(ex_id, exII::EX_NODAL, 0, & n_nodal_attr);
928 EX_CHECK_ERR(ex_err, "Error getting number of nodal attributes.");
929
930 if (n_nodal_attr > 0)
931 {
932 std::vector<std::vector<char>> attr_name_data
933 (n_nodal_attr, std::vector<char>(libmesh_max_str_length + 1));
934 std::vector<char *> attr_names(n_nodal_attr);
935 for (auto i : index_range(attr_names))
936 attr_names[i] = attr_name_data[i].data();
937
938 ex_err = exII::ex_get_attr_names(ex_id, exII::EX_NODAL, 0, attr_names.data());
939 EX_CHECK_ERR(ex_err, "Error getting nodal attribute names.");
940
941 for (auto i : index_range(attr_names))
942 if (std::string("bex_weight") == attr_names[i])
943 {
944 w.resize(num_nodes);
945 ex_err =
946 exII::ex_get_one_attr (ex_id, exII::EX_NODAL, 0, i+1,
947 MappedInputVector(w, _single_precision).data());
948 EX_CHECK_ERR(ex_err, "Error getting Bezier Extraction nodal weights");
949 }
950 }
951}

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 4853 of file exodusII_io_helper.C.

4858{
4859 LOG_SCOPE("read_nodeset_data()", "ExodusII_IO_Helper");
4860
4861 // This reads the sideset variable names into the local
4862 // sideset_var_names data structure.
4863 this->read_var_names(NODESET);
4864
4865 if (num_nodeset_vars)
4866 {
4867 // Read the nodeset data truth table
4868 std::vector<int> nset_var_tab(num_node_sets * num_nodeset_vars);
4869 ex_err = exII::ex_get_truth_table
4870 (ex_id,
4871 exII::EX_NODE_SET,
4874 nset_var_tab.data());
4875 EX_CHECK_ERR(ex_err, "Error reading nodeset variable truth table.");
4876
4877 // Set up/allocate space in incoming data structures.
4878 var_names = nodeset_var_names;
4879 node_boundary_ids.resize(num_nodeset_vars);
4880 bc_vals.resize(num_nodeset_vars);
4881
4882 // Read the nodeset data.
4883 //
4884 // Note: we assume that the functions
4885 // 1.) this->read_nodeset_info() and
4886 // 2.) this->read_all_nodesets()
4887 // have already been called, so that we already know e.g. how
4888 // many nodes are in each set, their ids, etc.
4889 //
4890 // TODO: As a future optimization, we could read only the values
4891 // requested by the user by looking at the input parameter
4892 // var_names and checking whether it already has entries in
4893 // it.
4894 int offset=0;
4895 for (int ns=0; ns<num_node_sets; ++ns)
4896 {
4897 offset += (ns > 0 ? num_nodes_per_set[ns-1] : 0);
4898 for (int var=0; var<num_nodeset_vars; ++var)
4899 {
4900 int is_present = nset_var_tab[num_nodeset_vars*ns + var];
4901
4902 if (is_present)
4903 {
4904 // Record the fact that this variable is defined on this nodeset.
4905 node_boundary_ids[var].insert(nodeset_ids[ns]);
4906
4907 // Note: the assumption here is that a previous call
4908 // to this->read_nodeset_info() has already set the
4909 // values of num_nodes_per_set, so we just use those values here.
4910 std::vector<Real> nset_var_vals(num_nodes_per_set[ns]);
4911 ex_err = exII::ex_get_var
4912 (ex_id,
4913 timestep,
4914 exII::EX_NODE_SET,
4915 var + 1, // 1-based nodeset variable index!
4916 nodeset_ids[ns],
4918 MappedInputVector(nset_var_vals, _single_precision).data());
4919 EX_CHECK_ERR(ex_err, "Error reading nodeset variable.");
4920
4921 for (int i=0; i<num_nodes_per_set[ns]; ++i)
4922 {
4923 // The read_all_nodesets() function now reads all the node ids into the
4924 // node_sets_node_list vector, which is of length "total_nodes_in_all_sets"
4925 // The old read_nodset() function is no longer called as far as I can tell,
4926 // and should probably be removed? The "offset" that we are using only
4927 // depends on the current nodeset index and the num_nodes_per_set vector,
4928 // which gets filled in by the call to read_all_nodesets().
4929 dof_id_type exodus_node_id = node_sets_node_list[i + offset];
4930
4931 // FIXME: We should use exodus_node_num_to_libmesh for this,
4932 // but it apparently is never set up, so just
4933 // subtract 1 from the Exodus node id.
4934 dof_id_type converted_node_id = exodus_node_id - 1;
4935
4936 // Make a NodeBCTuple key from the converted information.
4937 BoundaryInfo::NodeBCTuple key = std::make_tuple
4938 (converted_node_id, nodeset_ids[ns]);
4939
4940 // Store (node, b_id) tuples in bc_vals[var]
4941 bc_vals[var].emplace(key, nset_var_vals[i]);
4942 } // end for (i)
4943 } // end if (present)
4944 } // end for (var)
4945 } // end for (ns)
4946 } // end if (num_nodeset_vars)
4947}
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 1809 of file exodusII_io_helper.C.

1810{
1811 nodeset_ids.resize(num_node_sets);
1812 if (num_node_sets > 0)
1813 {
1814 ex_err = exII::ex_get_ids(ex_id,
1815 exII::EX_NODE_SET,
1816 nodeset_ids.data());
1817 EX_CHECK_ERR(ex_err, "Error retrieving nodeset information.");
1818 message("All nodeset information retrieved successfully.");
1819
1820 // Resize appropriate data structures -- only do this once outside the loop
1823 }
1824
1825 char name_buffer[libmesh_max_str_length+1];
1826 for (int i=0; i<num_node_sets; ++i)
1827 {
1828 ex_err = exII::ex_get_name(ex_id, exII::EX_NODE_SET,
1829 nodeset_ids[i], name_buffer);
1830 EX_CHECK_ERR(ex_err, "Error getting node set name.");
1831 id_to_ns_names[nodeset_ids[i]] = name_buffer;
1832 }
1833 message("All node set names retrieved successfully.");
1834}

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 2096 of file exodusII_io_helper.C.

2097{
2099 inquire(*this, exII::EX_INQ_TIME, "Error retrieving number of time steps");
2100}

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 828 of file exodusII_io_helper.C.

829{
830 // The QA records are four MAX_STR_LENGTH-byte character strings.
831 int num_qa_rec =
832 inquire(*this, exII::EX_INQ_QA, "Error retrieving number of QA records");
833
834 if (verbose)
835 libMesh::out << "Found "
836 << num_qa_rec
837 << " QA record(s) in the Exodus file."
838 << std::endl;
839
840 if (num_qa_rec > 0)
841 {
842 // Actual (num_qa_rec x 4) storage for strings. The object we
843 // pass to the Exodus API will just contain pointers into the
844 // qa_storage object, which will have all automatic memory
845 // management.
846 std::vector<std::vector<std::vector<char>>> qa_storage(num_qa_rec);
847 for (auto i : make_range(num_qa_rec))
848 {
849 qa_storage[i].resize(4);
850 for (auto j : make_range(4))
851 qa_storage[i][j].resize(libmesh_max_str_length+1);
852 }
853
854 // inner_array_t is a fixed-size array of 4 strings
855 typedef char * inner_array_t[4];
856
857 // There is at least one compiler (Clang 12.0.1) that complains about
858 // "a non-scalar type used in a pseudo-destructor expression" when
859 // we try to instantiate a std::vector of inner_array_t objects as in:
860 // std::vector<inner_array_t> qa_record(num_qa_rec);
861 // So, we instead attempt to achieve the same effect with a std::unique_ptr.
862 auto qa_record = std::make_unique<inner_array_t[]>(num_qa_rec);
863
864 // Create data structure to be passed to Exodus API by setting
865 // pointers to the actual strings which are in qa_storage.
866 for (auto i : make_range(num_qa_rec))
867 for (auto j : make_range(4))
868 qa_record[i][j] = qa_storage[i][j].data();
869
870 ex_err = exII::ex_get_qa (ex_id, qa_record.get());
871 EX_CHECK_ERR(ex_err, "Error reading the QA records.");
872
873 // Print the QA records
874 if (verbose)
875 {
876 for (auto i : make_range(num_qa_rec))
877 {
878 libMesh::out << "QA Record: " << i << std::endl;
879 for (auto j : make_range(4))
880 libMesh::out << qa_record[i][j] << std::endl;
881 }
882 }
883 }
884}

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 1878 of file exodusII_io_helper.C.

1879{
1880 LOG_SCOPE("read_sideset()", "ExodusII_IO_Helper");
1881
1882 libmesh_assert_less (id, ss_ids.size());
1883 libmesh_assert_less (id, num_sides_per_set.size());
1884 libmesh_assert_less (id, num_df_per_set.size());
1885 libmesh_assert_less_equal (offset, elem_list.size());
1886 libmesh_assert_less_equal (offset, side_list.size());
1887
1888 ex_err = exII::ex_get_set_param(ex_id,
1889 exII::EX_SIDE_SET,
1890 ss_ids[id],
1891 &num_sides_per_set[id],
1892 &num_df_per_set[id]);
1893 EX_CHECK_ERR(ex_err, "Error retrieving sideset parameters.");
1894 message("Parameters retrieved successfully for sideset: ", id);
1895
1896
1897 // It's OK for offset==elem_list.size() as long as num_sides_per_set[id]==0
1898 // because in that case we don't actually read anything...
1899#ifdef DEBUG
1900 if (static_cast<unsigned int>(offset) == elem_list.size() ||
1901 static_cast<unsigned int>(offset) == side_list.size() )
1902 libmesh_assert_equal_to (num_sides_per_set[id], 0);
1903#endif
1904
1905
1906 // Don't call ex_get_set unless there are actually sides there to get.
1907 // Exodus prints an annoying warning in DEBUG mode otherwise...
1908 if (num_sides_per_set[id] > 0)
1909 {
1910 ex_err = exII::ex_get_set(ex_id,
1911 exII::EX_SIDE_SET,
1912 ss_ids[id],
1913 &elem_list[offset],
1914 &side_list[offset]);
1915 EX_CHECK_ERR(ex_err, "Error retrieving sideset data.");
1916 message("Data retrieved successfully for sideset: ", id);
1917
1918 for (int i=0; i<num_sides_per_set[id]; i++)
1919 id_list[i+offset] = ss_ids[id];
1920 }
1921}

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 4321 of file exodusII_io_helper.C.

4327{
4328 LOG_SCOPE("read_sideset_data()", "ExodusII_IO_Helper");
4329
4330 // This reads the sideset variable names into the local
4331 // sideset_var_names data structure.
4332 this->read_var_names(SIDESET);
4333
4334 if (num_sideset_vars)
4335 {
4336 // Read the sideset data truth table
4337 std::vector<int> sset_var_tab(num_side_sets * num_sideset_vars);
4338 ex_err = exII::ex_get_truth_table
4339 (ex_id,
4340 exII::EX_SIDE_SET,
4343 sset_var_tab.data());
4344 EX_CHECK_ERR(ex_err, "Error reading sideset variable truth table.");
4345
4346 // Set up/allocate space in incoming data structures.
4347 var_names = sideset_var_names;
4348 side_ids.resize(num_sideset_vars);
4349 bc_vals.resize(num_sideset_vars);
4350
4351 // Read the sideset data.
4352 //
4353 // Note: we assume that read_sideset() has already been called
4354 // for each sideset, so the required values in elem_list and
4355 // side_list are already present.
4356 //
4357 // TODO: As a future optimization, we could read only the values
4358 // requested by the user by looking at the input parameter
4359 // var_names and checking whether it already has entries in
4360 // it. We could do the same thing with the input side_ids
4361 // container and only read values for requested sidesets.
4362 int offset=0;
4363 for (int ss=0; ss<num_side_sets; ++ss)
4364 {
4365 offset += (ss > 0 ? num_sides_per_set[ss-1] : 0);
4366 for (int var=0; var<num_sideset_vars; ++var)
4367 {
4368 int is_present = sset_var_tab[num_sideset_vars*ss + var];
4369
4370 if (is_present)
4371 {
4372 // Record the fact that this variable is defined on this sideset.
4373 side_ids[var].insert(ss_ids[ss]);
4374
4375 // Note: the assumption here is that a previous call
4376 // to this->read_sideset_info() has already set the
4377 // values of num_sides_per_set, so we just use those values here.
4378 std::vector<Real> sset_var_vals(num_sides_per_set[ss]);
4379 ex_err = exII::ex_get_var
4380 (ex_id,
4381 timestep,
4382 exII::EX_SIDE_SET,
4383 var + 1, // 1-based sideset variable index!
4384 ss_ids[ss],
4386 MappedInputVector(sset_var_vals, _single_precision).data());
4387 EX_CHECK_ERR(ex_err, "Error reading sideset variable.");
4388
4389 for (int i=0; i<num_sides_per_set[ss]; ++i)
4390 {
4391 dof_id_type exodus_elem_id = elem_list[i + offset];
4392 unsigned int exodus_side_id = side_list[i + offset];
4393
4394 // FIXME: We should use exodus_elem_num_to_libmesh for this,
4395 // but it apparently is never set up, so just
4396 // subtract 1 from the Exodus elem id.
4397 dof_id_type converted_elem_id = exodus_elem_id - 1;
4398
4399 // Map Exodus side id to libmesh side id.
4400 // Map from Exodus side ids to libmesh side ids.
4401 const auto & conv = get_conversion(mesh.elem_ptr(converted_elem_id)->type());
4402
4403 // Map from Exodus side id to libmesh side id.
4404 // Note: the mapping is defined on 0-based indices, so subtract
4405 // 1 before doing the mapping.
4406 unsigned int converted_side_id = conv.get_side_map(exodus_side_id - 1);
4407
4408 // Make a BCTuple key from the converted information.
4409 BoundaryInfo::BCTuple key = std::make_tuple
4410 (converted_elem_id,
4411 converted_side_id,
4412 ss_ids[ss]);
4413
4414 // Store (elem, side, b_id) tuples in bc_vals[var]
4415 bc_vals[var].emplace(key, sset_var_vals[i]);
4416 } // end for (i)
4417 } // end if (present)
4418 } // end for (var)
4419 } // end for (ss)
4420 } // end if (num_sideset_vars)
4421}
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 1774 of file exodusII_io_helper.C.

1775{
1776 ss_ids.resize(num_side_sets);
1777 if (num_side_sets > 0)
1778 {
1779 ex_err = exII::ex_get_ids(ex_id,
1780 exII::EX_SIDE_SET,
1781 ss_ids.data());
1782 EX_CHECK_ERR(ex_err, "Error retrieving sideset information.");
1783 message("All sideset information retrieved successfully.");
1784
1785 // Resize appropriate data structures -- only do this once outside the loop
1788
1789 // Inquire about the length of the concatenated side sets element list
1790 num_elem_all_sidesets = inquire(*this, exII::EX_INQ_SS_ELEM_LEN, "Error retrieving length of the concatenated side sets element list!");
1791
1795 }
1796
1797 char name_buffer[libmesh_max_str_length+1];
1798 for (int i=0; i<num_side_sets; ++i)
1799 {
1800 ex_err = exII::ex_get_name(ex_id, exII::EX_SIDE_SET,
1801 ss_ids[i], name_buffer);
1802 EX_CHECK_ERR(ex_err, "Error getting side set name.");
1803 id_to_ss_names[ss_ids[i]] = name_buffer;
1804 }
1805 message("All side set names retrieved successfully.");
1806}

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 2079 of file exodusII_io_helper.C.

2080{
2081 // Make sure we have an up-to-date count of the number of time steps in the file.
2082 this->read_num_time_steps();
2083
2084 if (num_time_steps > 0)
2085 {
2086 time_steps.resize(num_time_steps);
2087 ex_err = exII::ex_get_all_times
2088 (ex_id,
2089 MappedInputVector(time_steps, _single_precision).data());
2090 EX_CHECK_ERR(ex_err, "Error reading timesteps!");
2091 }
2092}

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 2168 of file exodusII_io_helper.C.

2169{
2170 switch (type)
2171 {
2172 case NODAL:
2174 break;
2175 case ELEMENTAL:
2177 break;
2178 case GLOBAL:
2180 break;
2181 case SIDESET:
2183 break;
2184 case NODESET:
2186 break;
2187 case ELEMSET:
2189 break;
2190 default:
2191 libmesh_error_msg("Unrecognized ExodusVarType " << type);
2192 }
2193}
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 2197 of file exodusII_io_helper.C.

2200{
2201 // First read and store the number of names we have
2202 ex_err = exII::ex_get_var_param(ex_id, var_type, &count);
2203 EX_CHECK_ERR(ex_err, "Error reading number of variables.");
2204
2205 // Do nothing if no variables are detected
2206 if (count == 0)
2207 return;
2208
2209 // Second read the actual names and convert them into a format we can use
2210 NamesData names_table(count, libmesh_max_str_length);
2211
2212 ex_err = exII::ex_get_var_names(ex_id,
2213 var_type,
2214 count,
2215 names_table.get_char_star_star()
2216 );
2217 EX_CHECK_ERR(ex_err, "Error reading variable names!");
2218
2219 if (verbose)
2220 {
2221 libMesh::out << "Read the variable(s) from the file:" << std::endl;
2222 for (int i=0; i<count; i++)
2223 libMesh::out << names_table.get_char_star(i) << std::endl;
2224 }
2225
2226 // Allocate enough space for our variable name strings.
2227 result.resize(count);
2228
2229 // Copy the char buffers into strings.
2230 for (int i=0; i<count; i++)
2231 result[i] = names_table.get_char_star(i); // calls string::op=(const char *)
2232}

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.

◆ 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 5372 of file exodusII_io_helper.C.

5373{
5375}

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 2476 of file exodusII_io_helper.C.

2480{
2481 if (this->set_unique_ids_from_maps)
2482 {
2483 // Exodus ids are always 1-based while libmesh ids are always
2484 // 0-based, so to make a libmesh unique_id here, we subtract 1
2485 // from the exodus_mapped_id to make it 0-based.
2486 auto exodus_mapped_id_zero_based =
2487 cast_int<dof_id_type>(exodus_mapped_id - 1);
2488
2489 // Set added_node's unique_id to "exodus_mapped_id_zero_based".
2490 dof_object->set_unique_id(cast_int<unique_id_type>(exodus_mapped_id_zero_based));
2491
2492 // Normally the Mesh is responsible for setting the unique_ids
2493 // of Nodes/Elems in a consistent manner, so when we set the unique_id
2494 // of a Node/Elem manually based on the {node,elem}_num_map, we need to
2495 // make sure that the "next" unique id assigned by the Mesh
2496 // will still be valid. We do this by making sure that the
2497 // next_unique_id is greater than the one we set manually. The
2498 // APIs for doing this are only defined when unique ids are
2499 // enabled.
2500#ifdef LIBMESH_ENABLE_UNIQUE_ID
2501 unique_id_type next_unique_id = mesh.next_unique_id();
2502 mesh.set_next_unique_id(std::max(next_unique_id, static_cast<unique_id_type>(exodus_mapped_id_zero_based + 1)));
2503#else
2504 // Avoid compiler warnings about the unused variable
2506#endif
2507 }
2508}
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
Definition dof_object.h:848
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:610
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 5345 of file exodusII_io_helper.C.

5346{
5347 _write_hdf5 = write_hdf5;
5348}

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 5351 of file exodusII_io_helper.C.

5352{
5353 // Opt mode error, because this may be exposed to users
5354 libmesh_error_msg_if (max_length > libmesh_max_str_length,
5355 "Exodus maximum name length is limited to " <<
5356 libmesh_max_str_length << " characters");
5357
5358 // Devel+dbg mode assertion, because developers should do better
5360
5361 _max_name_length = max_length;
5362}

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 5310 of file exodusII_io_helper.C.

5311{
5312 ex_err = exII::ex_update(ex_id);
5313 EX_CHECK_ERR(ex_err, "Error flushing buffers to file.");
5314}

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 5339 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 5365 of file exodusII_io_helper.C.

5366{
5368}

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 4997 of file exodusII_io_helper.C.

5002{
5003 LOG_SCOPE("write_element_values()", "ExodusII_IO_Helper");
5004
5005 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5006 return;
5007
5008 // Ask the file how many element vars it has, store it in the num_elem_vars variable.
5009 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_BLOCK, &num_elem_vars);
5010 EX_CHECK_ERR(ex_err, "Error reading number of elemental variables.");
5011
5012 // We will eventually loop over the element blocks (subdomains) and
5013 // write the data one block at a time. Build a data structure that
5014 // maps each subdomain to a list of element ids it contains.
5015 std::map<subdomain_id_type, std::vector<unsigned int>> subdomain_map;
5016 for (const auto & elem : mesh.active_element_ptr_range())
5017 subdomain_map[elem->subdomain_id()].push_back(elem->id());
5018
5019 // Use mesh.n_elem() to access into the values vector rather than
5020 // the number of elements the Exodus writer thinks the mesh has,
5021 // which may not include inactive elements.
5023
5024 // Sanity check: we must have an entry in vars_active_subdomains for
5025 // each variable that we are potentially writing out.
5026 libmesh_assert_equal_to
5027 (vars_active_subdomains.size(),
5028 static_cast<unsigned>(num_elem_vars));
5029
5030 // For each variable, create a 'data' array which holds all the elemental variable
5031 // values *for a given block* on this processor, then write that data vector to file
5032 // before moving onto the next block.
5033 for (unsigned int var_id=0; var_id<static_cast<unsigned>(num_elem_vars); ++var_id)
5034 {
5035 // The size of the subdomain map is the number of blocks.
5036 auto it = subdomain_map.begin();
5037
5038 // Reference to the set of active subdomains for the current variable.
5039 const auto & active_subdomains
5040 = vars_active_subdomains[var_id];
5041
5042 for (unsigned int j=0; it!=subdomain_map.end(); ++it, ++j)
5043 {
5044 // Skip any variable/subdomain pairs that are inactive.
5045 // Note that if active_subdomains is empty, it is interpreted
5046 // as being active on *all* subdomains.
5047 if (!(active_subdomains.empty() || active_subdomains.count(it->first)))
5048 continue;
5049
5050 // Get reference to list of elem ids which are in the
5051 // current subdomain and count, allocate storage to hold
5052 // data that will be written to file.
5053 const auto & elem_nums = it->second;
5054 const unsigned int num_elems_this_block =
5055 cast_int<unsigned int>(elem_nums.size());
5056 std::vector<Real> data(num_elems_this_block);
5057
5058 // variable-major ordering is:
5059 // (u1, u2, u3, ..., uN), (v1, v2, v3, ..., vN), ...
5060 // where N is the number of elements.
5061 for (unsigned int k=0; k<num_elems_this_block; ++k)
5062 data[k] = values[var_id*n_elem + elem_nums[k]];
5063
5064 ex_err = exII::ex_put_var
5065 (ex_id,
5066 timestep,
5067 exII::EX_ELEM_BLOCK,
5068 var_id+1,
5069 this->get_block_id(j),
5070 num_elems_this_block,
5071 MappedOutputVector(data, _single_precision).data());
5072
5073 EX_CHECK_ERR(ex_err, "Error writing element values.");
5074 }
5075 }
5076
5077 this->update();
5078}
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(), mesh, libMesh::MeshBase::n_elem(), num_elem_vars, libMesh::ParallelObject::processor_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 5082 of file exodusII_io_helper.C.

5089{
5090 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5091 return;
5092
5093 // Ask the file how many element vars it has, store it in the num_elem_vars variable.
5094 ex_err = exII::ex_get_variable_param(ex_id, exII::EX_ELEM_BLOCK, &num_elem_vars);
5095 EX_CHECK_ERR(ex_err, "Error reading number of elemental variables.");
5096
5097 // We will eventually loop over the element blocks (subdomains) and
5098 // write the data one block (subdomain) at a time. Build a data
5099 // structure that keeps track of how many elements are in each
5100 // subdomain. This will allow us to reserve space in the data vector
5101 // we are going to write.
5102 std::map<subdomain_id_type, unsigned int> subdomain_to_n_elem;
5103 for (const auto & elem : mesh.active_element_ptr_range())
5104 subdomain_to_n_elem[elem->subdomain_id()] += 1;
5105
5106 // Sanity check: we must have an entry in vars_active_subdomains for
5107 // each variable that we are potentially writing out.
5108 libmesh_assert_equal_to
5109 (vars_active_subdomains.size(),
5110 static_cast<unsigned>(num_elem_vars));
5111
5112 // The size of the subdomain map is the number of blocks.
5113 auto subdomain_to_n_elem_iter = subdomain_to_n_elem.begin();
5114
5115 // Store range of active Elem pointers. We are going to loop over
5116 // the elements n_vars * n_subdomains times, so let's make sure
5117 // the predicated iterators aren't slowing us down too much.
5118 ConstElemRange elem_range
5119 (mesh.active_elements_begin(),
5120 mesh.active_elements_end());
5121
5122 for (unsigned int sbd_idx=0;
5123 subdomain_to_n_elem_iter != subdomain_to_n_elem.end();
5124 ++subdomain_to_n_elem_iter, ++sbd_idx)
5125 for (unsigned int var_id=0; var_id<static_cast<unsigned>(num_elem_vars); ++var_id)
5126 {
5127 // Reference to the set of active subdomains for the current variable.
5128 const auto & active_subdomains
5129 = vars_active_subdomains[var_id];
5130
5131 // If the vars_active_subdomains container passed to this function
5132 // has an empty entry, it means the variable really is not active on
5133 // _any_ subdomains, not that it is active on _all_ subdomains. This
5134 // is just due to the way that we build the vars_active_subdomains
5135 // container.
5136 if (!active_subdomains.count(subdomain_to_n_elem_iter->first))
5137 continue;
5138
5139 // Vector to hold values that will be written to Exodus file.
5140 std::vector<Real> data;
5141 data.reserve(subdomain_to_n_elem_iter->second);
5142
5143 unsigned int values_offset = 0;
5144 for (auto & elem : elem_range)
5145 {
5146 // We'll use the Elem's subdomain id in several places below.
5147 subdomain_id_type sbd_id = elem->subdomain_id();
5148
5149 // Get reference to the list of variable names defining
5150 // the indexing for the current Elem's subdomain.
5151 auto subdomain_to_var_names_iter =
5152 subdomain_to_var_names.find(sbd_id);
5153
5154 // It's possible, but unusual, for there to be an Elem
5155 // from a subdomain that has no active variables from the
5156 // set of variables we are currently writing. If that
5157 // happens, we can just go to the next Elem because we
5158 // don't need to advance the offset into the values
5159 // vector, etc.
5160 if (subdomain_to_var_names_iter == subdomain_to_var_names.end())
5161 continue;
5162
5163 const auto & var_names_this_sbd
5164 = subdomain_to_var_names_iter->second;
5165
5166 // Only extract values if Elem is in the current subdomain.
5167 if (sbd_id == subdomain_to_n_elem_iter->first)
5168 {
5169 // Location of current var_id in the list of all variables on this
5170 // subdomain. FIXME: linear search but it's over a typically relatively
5171 // short vector of active variable names on this subdomain. We could do
5172 // a nested std::map<string,index> instead of a std::vector where the
5173 // location of the string is implicitly the index..
5174 auto pos =
5175 std::find(var_names_this_sbd.begin(),
5176 var_names_this_sbd.end(),
5177 derived_var_names[var_id]);
5178
5179 libmesh_error_msg_if(pos == var_names_this_sbd.end(),
5180 "Derived name " << derived_var_names[var_id] << " not found!");
5181
5182 // Find the current variable's location in the list of all variable
5183 // names on the current Elem's subdomain.
5184 auto true_index =
5185 std::distance(var_names_this_sbd.begin(), pos);
5186
5187 data.push_back(values[values_offset + true_index]);
5188 }
5189
5190 // The "true" offset is how much we have to advance the index for each Elem
5191 // in this subdomain.
5192 auto true_offset = var_names_this_sbd.size();
5193
5194 // Increment to the next Elem's values
5195 values_offset += true_offset;
5196 } // for elem
5197
5198 // Now write 'data' to Exodus file, in single precision if requested.
5199 if (!data.empty())
5200 {
5201 ex_err = exII::ex_put_var
5202 (ex_id,
5203 timestep,
5204 exII::EX_ELEM_BLOCK,
5205 var_id+1,
5206 this->get_block_id(sbd_idx),
5207 data.size(),
5208 MappedOutputVector(data, _single_precision).data());
5209
5210 EX_CHECK_ERR(ex_err, "Error writing element values.");
5211 }
5212 } // for each var_id
5213
5214 this->update();
5215}
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(), 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 2959 of file exodusII_io_helper.C.

2960{
2961 LOG_SCOPE("write_elements()", "ExodusII_IO_Helper");
2962
2963 // Map from block ID to a vector of element IDs in that block. Element
2964 // IDs are now of type dof_id_type, subdomain IDs are of type subdomain_id_type.
2965 subdomain_id_type subdomain_id_end = 0;
2966 int c0polyhedron_face_block_id = -1;
2967 auto subdomain_map = build_subdomain_map(mesh,
2968 _add_sides,
2969 subdomain_id_end,
2970 c0polyhedron_face_block_id);
2971
2972 if ((_run_only_on_proc0) && (this->processor_id() != 0))
2973 return;
2974
2975 // element map vector
2976 num_elem_blk = cast_int<int>(subdomain_map.size());
2977 block_ids.resize(num_elem_blk);
2978
2979 std::vector<int> elem_blk_id;
2980 std::vector<int> num_elem_this_blk_vec;
2981 std::vector<int> num_nodes_per_elem_vec;
2982 std::vector<int> num_edges_per_elem_vec;
2983 std::vector<int> num_faces_per_elem_vec;
2984 std::vector<int> num_attr_vec;
2985 NamesData elem_type_table(num_elem_blk, _max_name_length);
2986
2987 // Note: It appears that there is a bug in exodusII::ex_put_name where
2988 // the index returned from the ex_id_lkup is erroneously used. For now
2989 // the work around is to use the alternative function ex_put_names, but
2990 // this function requires a char ** data structure.
2991 NamesData names_table(num_elem_blk, _max_name_length);
2992
2993 num_elem = 0;
2994 bool has_c0polygon_blocks = false;
2995 bool has_c0polyhedron_blocks = false;
2996 int c0polyhedron_total_faces = 0;
2997 int c0polyhedron_total_face_nodes = 0;
2998
2999 // counter indexes into the block_ids vector
3000 unsigned int counter = 0;
3001 for (auto & [subdomain_id, element_id_vec] : subdomain_map)
3002 {
3003 block_ids[counter] = subdomain_id;
3004
3005 const ElemType elem_t = (subdomain_id >= subdomain_id_end) ?
3006 ElemType(subdomain_id - subdomain_id_end) :
3007 mesh.elem_ref(element_id_vec[0]).type();
3008
3009 if (subdomain_id >= subdomain_id_end)
3010 {
3012 libmesh_assert(element_id_vec.size() == 1);
3013 num_elem_this_blk_vec.push_back
3014 (cast_int<int>(element_id_vec[0]));
3015 names_table.push_back_entry
3016 (Utility::enum_to_string<ElemType>(elem_t));
3017 }
3018 else
3019 {
3020 libmesh_assert(!element_id_vec.empty());
3021 num_elem_this_blk_vec.push_back
3022 (cast_int<int>(element_id_vec.size()));
3023
3024 std::string block_name = mesh.subdomain_name(subdomain_id);
3025 if (block_name.empty() && elem_t == C0POLYGON)
3026 block_name = "NSIDED_" + std::to_string(counter + 1);
3027 if (block_name.empty() && elem_t == C0POLYHEDRON)
3028 block_name = "NFACED_" + std::to_string(counter + 1);
3029 names_table.push_back_entry(block_name);
3030 }
3031
3032 num_elem += num_elem_this_blk_vec.back();
3033
3034 // Use the first element in this block to get representative information.
3035 // Note that Exodus assumes all elements in a block are of the same type!
3036 // We are using that same assumption here!
3037 const auto & conv = get_conversion(elem_t);
3038 int num_edges_per_elem = 0;
3039 int num_faces_per_elem = 0;
3040 if (elem_t == C0POLYGON)
3041 {
3042 if (subdomain_id >= subdomain_id_end)
3043 libmesh_not_implemented_msg("Support for C0POLYGON side blocks not yet implemented");
3044
3045 has_c0polygon_blocks = true;
3047
3048 for (auto elem_id : element_id_vec)
3049 {
3050 const Elem & elem = mesh.elem_ref(elem_id);
3051
3052 libmesh_error_msg_if(elem.type() != C0POLYGON,
3053 "Error: Exodus requires all elements with a given subdomain ID "
3054 "to be the same type.\n"
3055 << "Can't write both "
3056 << Utility::enum_to_string(elem.type())
3057 << " and C0POLYGON in the same block!");
3058
3059 num_nodes_per_elem += cast_int<int>(elem.n_nodes());
3060 }
3061 }
3062 else if (elem_t == C0POLYHEDRON)
3063 {
3064 if (subdomain_id >= subdomain_id_end)
3065 libmesh_not_implemented_msg("Support for C0POLYHEDRON side blocks not yet implemented");
3066
3067 has_c0polyhedron_blocks = true;
3069
3070 for (auto elem_id : element_id_vec)
3071 {
3072 const Elem & elem = mesh.elem_ref(elem_id);
3073
3074 libmesh_error_msg_if(elem.type() != C0POLYHEDRON,
3075 "Error: Exodus requires all elements with a given subdomain ID "
3076 "to be the same type.\n"
3077 << "Can't write both "
3078 << Utility::enum_to_string(elem.type())
3079 << " and C0POLYHEDRON in the same block!");
3080
3081 const int elem_n_sides = cast_int<int>(elem.n_sides());
3082 num_faces_per_elem += elem_n_sides;
3083 c0polyhedron_total_faces += elem_n_sides;
3084
3085 for (auto s : elem.side_index_range())
3086 c0polyhedron_total_face_nodes += cast_int<int>(elem.nodes_on_side(s).size());
3087 }
3088 }
3089 else
3090 {
3093 libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
3094 }
3095
3096 elem_blk_id.push_back(subdomain_id);
3097 elem_type_table.push_back_entry(conv.exodus_elem_type().c_str());
3098 num_nodes_per_elem_vec.push_back(num_nodes_per_elem);
3099 num_attr_vec.push_back(0); // we don't currently use elem block attributes.
3100 num_edges_per_elem_vec.push_back(num_edges_per_elem); // We don't currently store any edge blocks
3101 num_faces_per_elem_vec.push_back(num_faces_per_elem);
3102 ++counter;
3103 }
3104
3105 if (has_c0polyhedron_blocks)
3106 {
3107 libmesh_assert_equal_to(num_face_blk, 1);
3108 libmesh_assert_equal_to(num_face, c0polyhedron_total_faces);
3109 }
3110
3111 // Here we reserve() space so that we can push_back() onto the
3112 // elem_num_map in the loops below.
3113 this->elem_num_map.reserve(num_elem);
3114
3115 // In the case of discontinuous plotting we initialize a map from
3116 // (element, node) pairs to the corresponding discontinuous node index.
3117 // This ordering must match the ordering used in write_nodal_coordinates.
3118 //
3119 // Note: This map takes the place of the libmesh_node_num_to_exodus map in
3120 // the discontinuous case.
3121 std::map<std::pair<dof_id_type, unsigned int>, dof_id_type> discontinuous_node_indices;
3122 dof_id_type node_counter = 1; // Exodus numbering is 1-based
3123 if (use_discontinuous)
3124 {
3125 for (const auto & elem : mesh.active_element_ptr_range())
3126 for (auto n : elem->node_index_range())
3127 discontinuous_node_indices[std::make_pair(elem->id(),n)] =
3128 node_counter++;
3129 }
3130 else
3131 node_counter = mesh.max_node_id() + 1; // Exodus numbering is 1-based
3132
3133 if (_add_sides)
3134 {
3135 for (const Elem * elem : mesh.active_element_ptr_range())
3136 {
3137 // We'll use "past-the-end" indices to indicate side node
3138 // copies
3139 unsigned int local_node_index = elem->n_nodes();
3140
3141 for (auto s : elem->side_index_range())
3142 {
3144 continue;
3145
3146 const std::vector<unsigned int> side_nodes =
3147 elem->nodes_on_side(s);
3148
3149 for (auto n : index_range(side_nodes))
3150 {
3151 libmesh_ignore(n);
3152 discontinuous_node_indices
3153 [std::make_pair(elem->id(),local_node_index++)] =
3154 node_counter++;
3155 }
3156 }
3157 }
3158 }
3159
3160 // Reference to the BoundaryInfo object for convenience.
3161 const BoundaryInfo & bi = mesh.get_boundary_info();
3162
3163 // Build list of (elem, edge, id) triples
3164 std::vector<BoundaryInfo::BCTuple> edge_tuples = bi.build_edge_list();
3165
3166 // Build the connectivity array for each edge block. The connectivity array
3167 // is a vector<int> with "num_edges * num_nodes_per_edge" entries. We write
3168 // the Exodus node numbers to the connectivity arrays so that they can
3169 // be used directly in the calls to exII::ex_put_conn() below. We also keep
3170 // track of the ElemType and the number of nodes for each boundary_id. All
3171 // edges with a given boundary_id must be of the same type.
3172 std::map<boundary_id_type, std::vector<int>> edge_id_to_conn;
3173 std::map<boundary_id_type, std::pair<ElemType, unsigned int>> edge_id_to_elem_type;
3174
3175 std::unique_ptr<const Elem> edge;
3176 for (const auto & t : edge_tuples)
3177 {
3178 dof_id_type elem_id = std::get<0>(t);
3179 unsigned int edge_id = std::get<1>(t);
3180 boundary_id_type b_id = std::get<2>(t);
3181
3182 // Build the edge in question
3183 mesh.elem_ptr(elem_id)->build_edge_ptr(edge, edge_id);
3184
3185 // Error checking: make sure that all edges in this block are
3186 // the same geometric type.
3187 if (const auto check_it = edge_id_to_elem_type.find(b_id);
3188 check_it == edge_id_to_elem_type.end())
3189 {
3190 // Keep track of the ElemType and number of nodes in this boundary id.
3191 edge_id_to_elem_type[b_id] = std::make_pair(edge->type(), edge->n_nodes());
3192 }
3193 else
3194 {
3195 // Make sure the existing data is consistent
3196 const auto & val_pair = check_it->second;
3197 libmesh_error_msg_if(val_pair.first != edge->type() || val_pair.second != edge->n_nodes(),
3198 "All edges in a block must have same geometric type.");
3199 }
3200
3201 // Get reference to the connectivity array for this block
3202 auto & conn = edge_id_to_conn[b_id];
3203
3204 // For each node on the edge, look up the exodus node id and
3205 // store it in the conn array. Note: all edge types have
3206 // identity node mappings so we don't bother with Conversion
3207 // objects here.
3208 for (auto n : edge->node_index_range())
3209 {
3210 // We look up Exodus node numbers differently if we are
3211 // writing a discontinuous Exodus file.
3212 int exodus_node_id = -1;
3213
3214 if (!use_discontinuous)
3215 {
3216 dof_id_type libmesh_node_id = edge->node_ptr(n)->id();
3217 exodus_node_id = libmesh_map_find
3218 (libmesh_node_num_to_exodus, cast_int<int>(libmesh_node_id));
3219 }
3220 else
3221 {
3222 // Get the node on the element containing this edge
3223 // which corresponds to edge node n. Then use that id to look up
3224 // the exodus_node_id in the discontinuous_node_indices map.
3225 unsigned int pn = mesh.elem_ptr(elem_id)->local_edge_node(edge_id, n);
3226 exodus_node_id = libmesh_map_find
3227 (discontinuous_node_indices, std::make_pair(elem_id, pn));
3228 }
3229
3230 conn.push_back(exodus_node_id);
3231 }
3232 }
3233
3234 // Make sure we have the same number of edge ids that we thought we would.
3235 libmesh_assert(static_cast<int>(edge_id_to_conn.size()) == num_edge_blk);
3236
3237 // Build data structures describing edge blocks. This information must be
3238 // be passed to exII::ex_put_concat_all_blocks() at the same time as the
3239 // information about elem blocks.
3240 std::vector<int> edge_blk_id;
3241 NamesData edge_type_table(num_edge_blk, _max_name_length);
3242 std::vector<int> num_edge_this_blk_vec;
3243 std::vector<int> num_nodes_per_edge_vec;
3244 std::vector<int> num_attr_edge_vec;
3245
3246 // We also build a data structure of edge block names which can
3247 // later be passed to exII::ex_put_names().
3248 NamesData edge_block_names_table(num_edge_blk, _max_name_length);
3249 NamesData face_block_names_table(num_face_blk, _max_name_length);
3250 if (has_c0polyhedron_blocks)
3251 face_block_names_table.push_back_entry("NSIDED_FACES");
3252
3253 // Note: We are going to use the edge **boundary** ids as **block** ids.
3254 for (const auto & pr : edge_id_to_conn)
3255 {
3256 // Store the edge block id in the array to be passed to Exodus.
3257 boundary_id_type id = pr.first;
3258 edge_blk_id.push_back(id);
3259
3260 // Set Exodus element type and number of nodes for this edge block.
3261 const auto & elem_type_node_count = edge_id_to_elem_type[id];
3262 const auto & conv = get_conversion(elem_type_node_count.first);
3263 edge_type_table.push_back_entry(conv.exodus_type.c_str());
3264 num_nodes_per_edge_vec.push_back(elem_type_node_count.second);
3265
3266 // The number of edges is the number of entries in the connectivity
3267 // array divided by the number of nodes per edge.
3268 num_edge_this_blk_vec.push_back(pr.second.size() / elem_type_node_count.second);
3269
3270 // We don't store any attributes currently
3271 num_attr_edge_vec.push_back(0);
3272
3273 // Store the name of this edge block
3274 edge_block_names_table.push_back_entry(bi.get_edgeset_name(id));
3275 }
3276
3277 if (has_c0polygon_blocks || has_c0polyhedron_blocks)
3278 {
3279 // ex_put_concat_all_blocks() does not define the per-polytope
3280 // entity count arrays required by NSIDED/NFACED blocks in all supported
3281 // Exodus versions. Define blocks individually through ex_put_block().
3282 if (has_c0polyhedron_blocks)
3283 {
3284 ex_err = exII::ex_put_block(ex_id,
3285 exII::EX_FACE_BLOCK,
3286 c0polyhedron_face_block_id,
3287 "NSIDED",
3288 c0polyhedron_total_faces,
3289 c0polyhedron_total_face_nodes,
3290 0,
3291 0,
3292 0);
3293 EX_CHECK_ERR(ex_err, "Error writing polyhedron face block.");
3294 }
3295
3296 for (auto i : index_range(elem_blk_id))
3297 {
3298 ex_err = exII::ex_put_block(ex_id,
3299 exII::EX_ELEM_BLOCK,
3300 elem_blk_id[i],
3301 elem_type_table.get_char_star(cast_int<int>(i)),
3302 num_elem_this_blk_vec[i],
3303 num_nodes_per_elem_vec[i],
3304 num_edges_per_elem_vec[i],
3305 num_faces_per_elem_vec[i],
3306 num_attr_vec[i]);
3307 EX_CHECK_ERR(ex_err, "Error writing element block.");
3308 }
3309
3310 for (auto i : index_range(edge_blk_id))
3311 {
3312 ex_err = exII::ex_put_block(ex_id,
3313 exII::EX_EDGE_BLOCK,
3314 edge_blk_id[i],
3315 edge_type_table.get_char_star(cast_int<int>(i)),
3316 num_edge_this_blk_vec[i],
3317 num_nodes_per_edge_vec[i],
3318 0,
3319 0,
3320 num_attr_edge_vec[i]);
3321 EX_CHECK_ERR(ex_err, "Error writing edge block.");
3322 }
3323 }
3324 else
3325 {
3326 // Zero-initialize and then fill in an exII::ex_block_params struct
3327 // with the data we have collected. This new API replaces the old
3328 // exII::ex_put_concat_elem_block() API, and will eventually allow
3329 // us to also allocate space for edge/face blocks if desired.
3330 //
3331 // TODO: It seems like we should be able to take advantage of the
3332 // optimization where you set define_maps==1, but when I tried this
3333 // I got the error: "failed to find node map size". I think the
3334 // problem is that we need to first specify a nonzero number of
3335 // node/elem maps during the call to ex_put_init_ext() in order for
3336 // this to work correctly.
3337 exII::ex_block_params params = {};
3338
3339 // Set pointers for information about elem blocks.
3340 params.elem_blk_id = elem_blk_id.data();
3341 params.elem_type = elem_type_table.get_char_star_star();
3342 params.num_elem_this_blk = num_elem_this_blk_vec.data();
3343 params.num_nodes_per_elem = num_nodes_per_elem_vec.data();
3344 params.num_edges_per_elem = num_edges_per_elem_vec.data();
3345 params.num_faces_per_elem = num_faces_per_elem_vec.data();
3346 params.num_attr_elem = num_attr_vec.data();
3347 params.define_maps = 0;
3348
3349 // Set pointers to edge block information only if we actually have some.
3350 if (num_edge_blk)
3351 {
3352 params.edge_blk_id = edge_blk_id.data();
3353 params.edge_type = edge_type_table.get_char_star_star();
3354 params.num_edge_this_blk = num_edge_this_blk_vec.data();
3355 params.num_nodes_per_edge = num_nodes_per_edge_vec.data();
3356 params.num_attr_edge = num_attr_edge_vec.data();
3357 }
3358
3359 ex_err = exII::ex_put_concat_all_blocks(ex_id, &params);
3360 EX_CHECK_ERR(ex_err, "Error writing element blocks.");
3361 }
3362
3363 // This counter is used to fill up the libmesh_elem_num_to_exodus map in the loop below.
3364 unsigned libmesh_elem_num_to_exodus_counter = 0;
3365
3366 // We need these later if we're adding fake sides, but we don't need
3367 // to recalculate it.
3368 auto num_elem_this_blk_it = num_elem_this_blk_vec.begin();
3369
3370 // We write "fake" ids to the elem_num_map when adding fake sides.
3371 // I don't think it's too important exactly what fake ids are used,
3372 // as long as they don't conflict with any other ids that are
3373 // already in the elem_num_map.
3374 auto next_fake_id = mesh.max_elem_id() + 1; // 1-based numbering in Exodus
3375#ifdef LIBMESH_ENABLE_UNIQUE_ID
3376 if (this->set_unique_ids_from_maps)
3377 next_fake_id = mesh.next_unique_id();
3378#endif
3379
3380 std::vector<int> face_connect;
3381 std::vector<int> c0polyhedron_face_node_counts;
3382 face_connect.reserve(c0polyhedron_total_face_nodes);
3383 c0polyhedron_face_node_counts.reserve(c0polyhedron_total_faces);
3384 int next_c0polyhedron_face_id = 1;
3385
3386 const auto get_exodus_node_id = [&](const Elem &elem,
3387 dof_id_type elem_id,
3388 unsigned int elem_node_index)
3389 -> int
3390 {
3391 if (!use_discontinuous)
3392 return libmesh_map_find(libmesh_node_num_to_exodus,
3393 cast_int<int>(elem.node_id(elem_node_index)));
3394
3395 return cast_int<int>(libmesh_map_find(discontinuous_node_indices,
3396 std::make_pair(elem_id, elem_node_index)));
3397 };
3398
3399 for (auto & [subdomain_id, element_id_vec] : subdomain_map)
3400 {
3401 // Use the first element in the block to get representative
3402 // information for a "real" block. Note that Exodus assumes all
3403 // elements in a block are of the same type! We are using that
3404 // same assumption here!
3405 const ElemType elem_t = (subdomain_id >= subdomain_id_end) ?
3406 ElemType(subdomain_id - subdomain_id_end) :
3407 mesh.elem_ref(element_id_vec[0]).type();
3408
3409 const auto & conv = get_conversion(elem_t);
3410 const bool is_c0polygon_block = (elem_t == C0POLYGON);
3411 const bool is_c0polyhedron_block = (elem_t == C0POLYHEDRON);
3412 const bool is_variable_connectivity_block =
3413 is_c0polygon_block || is_c0polyhedron_block;
3414 std::vector<int> c0polygon_node_counts;
3415 std::vector<int> c0polyhedron_face_counts;
3416
3417 if (is_variable_connectivity_block && subdomain_id >= subdomain_id_end)
3418 libmesh_not_implemented_msg("Support for " <<
3419 Utility::enum_to_string(elem_t) <<
3420 " side blocks not yet implemented");
3421
3422 if (!is_variable_connectivity_block)
3423 {
3426 libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
3427 }
3428
3429 // If this is a *real* block, we just loop over vectors of
3430 // element ids to add.
3431 if (subdomain_id < subdomain_id_end)
3432 {
3433 if (is_variable_connectivity_block)
3434 connect.clear();
3435 if (is_c0polygon_block)
3436 c0polygon_node_counts.reserve(element_id_vec.size());
3437 else if (is_c0polyhedron_block)
3438 c0polyhedron_face_counts.reserve(element_id_vec.size());
3439 else
3440 connect.resize(element_id_vec.size()*num_nodes_per_elem);
3441
3442 const auto add_c0polygon_connectivity =
3443 [&](const Elem &elem, dof_id_type elem_id)
3444 {
3445 c0polygon_node_counts.push_back(cast_int<int>(elem.n_nodes()));
3446 for (auto elem_node_index : elem.node_index_range())
3447 connect.push_back(get_exodus_node_id(elem, elem_id, elem_node_index));
3448
3449 };
3450
3451 const auto add_c0polyhedron_connectivity =
3452 [&](const Elem &elem, dof_id_type elem_id)
3453 {
3454 c0polyhedron_face_counts.push_back(cast_int<int>(elem.n_sides()));
3455
3456 for (auto s: elem.side_index_range())
3457 {
3458 connect.push_back(next_c0polyhedron_face_id++);
3459
3460 const std::vector<unsigned int> side_nodes = elem.nodes_on_side(s);
3461 c0polyhedron_face_node_counts.push_back(cast_int<int>(side_nodes.size()));
3462
3463 for (const auto elem_node_index : side_nodes)
3464 face_connect.push_back(
3465 get_exodus_node_id(elem, elem_id, elem_node_index));
3466 }
3467 };
3468
3469 const auto add_fixed_connectivity =
3470 [&](const Elem &elem, dof_id_type elem_id, std::size_t elem_index)
3471 {
3472 for (unsigned int j = 0;
3473 j < static_cast<unsigned int>(num_nodes_per_elem);
3474 ++j)
3475 {
3476 const auto connect_index =
3477 cast_int<unsigned int>((elem_index * num_nodes_per_elem) + j);
3478 const auto elem_node_index = conv.get_inverse_node_map(j);
3479 connect[connect_index] =
3480 get_exodus_node_id(elem, elem_id, elem_node_index);
3481 }
3482 };
3483
3484 for (auto i : index_range(element_id_vec))
3485 {
3486 unsigned int elem_id = element_id_vec[i];
3487 libmesh_elem_num_to_exodus[elem_id] = ++libmesh_elem_num_to_exodus_counter; // 1-based indexing for Exodus
3488
3489 const Elem & elem = mesh.elem_ref(elem_id);
3490
3491 // We *might* be able to get away with writing mixed element
3492 // types which happen to have the same number of nodes, but
3493 // do we actually *want* to get away with that?
3494 // .) No visualization software would be able to handle it.
3495 // .) There'd be no way for us to read it back in reliably.
3496 // .) Even elements with the same number of nodes may have different connectivities (?)
3497
3498 // This needs to be more than an assert so we don't fail
3499 // with a mysterious segfault while trying to write mixed
3500 // element meshes in optimized mode.
3501 libmesh_error_msg_if(elem.type() != conv.libmesh_elem_type(),
3502 "Error: Exodus requires all elements with a given subdomain ID to be the same type.\n"
3503 << "Can't write both "
3504 << Utility::enum_to_string(elem.type())
3505 << " and "
3506 << Utility::enum_to_string(conv.libmesh_elem_type())
3507 << " in the same block!");
3508
3509 if (is_c0polygon_block)
3510 add_c0polygon_connectivity(elem, elem_id);
3511 else if (is_c0polyhedron_block)
3512 add_c0polyhedron_connectivity(elem, elem_id);
3513 else
3514 add_fixed_connectivity(elem, elem_id, i);
3515
3516 // push_back() either elem_id+1 or the current Elem's
3517 // unique_id+1 into the elem_num_map, depending on the value
3518 // of the set_unique_ids_from_maps flag.
3519 if (this->set_unique_ids_from_maps)
3520 this->elem_num_map.push_back(elem.unique_id() + 1);
3521 else
3522 this->elem_num_map.push_back(elem_id + 1);
3523
3524 } // end for(i)
3525 }
3526 else // subdomain_id >= subdomain_id_end
3527 {
3528 // If this is a "fake" block of added sides, we build those as
3529 // we go.
3531
3532 libmesh_assert(num_elem_this_blk_it != num_elem_this_blk_vec.end());
3533 num_elem_this_blk = *num_elem_this_blk_it;
3534
3536
3537 std::size_t connect_index = 0;
3538 for (const auto & elem : mesh.active_element_ptr_range())
3539 {
3540 unsigned int local_node_index = elem->n_nodes();
3541
3542 for (auto s : elem->side_index_range())
3543 {
3545 continue;
3546
3547 if (elem->side_type(s) != elem_t)
3548 continue;
3549
3550 const std::vector<unsigned int> side_nodes =
3551 elem->nodes_on_side(s);
3552
3553 for (auto n : index_range(side_nodes))
3554 {
3555 libmesh_ignore(n);
3556 const int exodus_node_id = libmesh_map_find
3557 (discontinuous_node_indices,
3558 std::make_pair(elem->id(), local_node_index++));
3559 libmesh_assert_less(connect_index, connect.size());
3560 connect[connect_index++] = exodus_node_id;
3561 }
3562 }
3563 }
3564
3565 // Store num_elem_this_blk "fake" ids into the
3566 // elem_num_map. Use a traditional for-loop to avoid unused
3567 // variable warnings about the loop counter.
3568 for (int i=0; i<num_elem_this_blk; ++i)
3569 this->elem_num_map.push_back(next_fake_id++);
3570 }
3571
3572 ++num_elem_this_blk_it;
3573
3574 ex_err = exII::ex_put_conn
3575 (ex_id,
3576 exII::EX_ELEM_BLOCK,
3577 subdomain_id,
3578 is_c0polyhedron_block ? nullptr : connect.data(), // node_conn
3579 nullptr, // elem_edge_conn (unused)
3580 is_c0polyhedron_block ? connect.data() : nullptr);
3581 EX_CHECK_ERR(ex_err, "Error writing element connectivities");
3582
3583 if (is_c0polygon_block)
3584 {
3585 ex_err = exII::ex_put_entity_count_per_polyhedra
3586 (ex_id,
3587 exII::EX_ELEM_BLOCK,
3588 subdomain_id,
3589 c0polygon_node_counts.data());
3590 EX_CHECK_ERR(ex_err, "Error writing polygon node counts");
3591 }
3592 if (is_c0polyhedron_block)
3593 {
3594 ex_err = exII::ex_put_entity_count_per_polyhedra
3595 (ex_id,
3596 exII::EX_ELEM_BLOCK,
3597 subdomain_id,
3598 c0polyhedron_face_counts.data());
3599 EX_CHECK_ERR(ex_err, "Error writing polyhedron face counts");
3600 }
3601 } // end for (auto & [subdomain_id, element_id_vec] : subdomain_map)
3602
3603 if (has_c0polyhedron_blocks)
3604 {
3605 libmesh_assert_equal_to(c0polyhedron_face_node_counts.size(),
3606 cast_int<std::size_t>(num_face));
3607 libmesh_assert_equal_to(next_c0polyhedron_face_id, num_face + 1);
3608
3609 ex_err = exII::ex_put_conn
3610 (ex_id,
3611 exII::EX_FACE_BLOCK,
3612 c0polyhedron_face_block_id,
3613 face_connect.data(), // node_conn
3614 nullptr, // elem_edge_conn (unused)
3615 nullptr); // elem_face_conn (unused)
3616 EX_CHECK_ERR(ex_err, "Error writing polyhedron face connectivities");
3617
3618 ex_err = exII::ex_put_entity_count_per_polyhedra
3619 (ex_id,
3620 exII::EX_FACE_BLOCK,
3621 c0polyhedron_face_block_id,
3622 c0polyhedron_face_node_counts.data());
3623 EX_CHECK_ERR(ex_err, "Error writing polyhedron face node counts");
3624 }
3625
3626 // write out the element number map that we created
3627 ex_err = exII::ex_put_elem_num_map(ex_id, elem_num_map.data());
3628 EX_CHECK_ERR(ex_err, "Error writing element map");
3629
3630 // Write out the block names
3631 if (num_elem_blk > 0)
3632 {
3633 ex_err = exII::ex_put_names(ex_id, exII::EX_ELEM_BLOCK, names_table.get_char_star_star());
3634 EX_CHECK_ERR(ex_err, "Error writing element block names");
3635 }
3636
3637 if (num_face_blk > 0)
3638 {
3639 ex_err = exII::ex_put_names
3640 (ex_id,
3641 exII::EX_FACE_BLOCK,
3642 face_block_names_table.get_char_star_star());
3643 EX_CHECK_ERR(ex_err, "Error writing face block names");
3644 }
3645
3646 // Write out edge blocks if we have any
3647 for (const auto & pr : edge_id_to_conn)
3648 {
3649 ex_err = exII::ex_put_conn
3650 (ex_id,
3651 exII::EX_EDGE_BLOCK,
3652 pr.first,
3653 pr.second.data(), // node_conn
3654 nullptr, // elem_edge_conn (unused)
3655 nullptr); // elem_face_conn (unused)
3656 EX_CHECK_ERR(ex_err, "Error writing element connectivities");
3657 }
3658
3659 // Write out the edge block names, if any.
3660 if (num_edge_blk > 0)
3661 {
3662 ex_err = exII::ex_put_names
3663 (ex_id,
3664 exII::EX_EDGE_BLOCK,
3665 edge_block_names_table.get_char_star_star());
3666 EX_CHECK_ERR(ex_err, "Error writing edge block names");
3667 }
3668}
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:835
dof_id_type id() const
Definition dof_object.h:819
This is the base class from which all geometric element types are derived.
Definition elem.h:96
static const 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:643
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 ...
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:2484
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:1887
virtual const Elem & elem_ref(const dof_id_type i) const
Definition mesh_base.h:788
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::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::MeshBase::subdomain_name(), libMesh::Elem::type(), libMesh::Elem::type_to_n_nodes_map, and libMesh::DofObject::unique_id().

◆ 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 4578 of file exodusII_io_helper.C.

4583{
4584 LOG_SCOPE("write_elemset_data()", "ExodusII_IO_Helper");
4585
4586 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4587 return;
4588
4589 // Write the elemset variable names to file. This function should
4590 // only be called once for ELEMSET variables, repeated calls to
4591 // write_var_names() overwrites/changes the order of names that were
4592 // there previously, and will mess up any data that has already been
4593 // written.
4594 this->write_var_names(ELEMSET, var_names);
4595
4596 // We now call the API to read the elemset info even though we are
4597 // in the middle of writing. This is a bit counter-intuitive, but it
4598 // seems to work provided that you have already written the mesh
4599 // itself... read_elemset_info() fills in the following data
4600 // members:
4601 // .) id_to_elemset_names
4602 // .) num_elems_per_set
4603 // .) num_elem_df_per_set
4604 // .) elemset_list
4605 // .) elemset_id_list
4606 // .) id_to_elemset_names
4607 this->read_elemset_info();
4608
4609 // The "truth" table for elemset variables. elemset_var_tab is a
4610 // logically (num_elem_sets x num_elemset_vars) integer array of 0s and
4611 // 1s indicating which elemsets a given elemset variable is defined
4612 // on.
4613 std::vector<int> elemset_var_tab(num_elem_sets * var_names.size());
4614
4615 int offset=0;
4616 for (int es=0; es<num_elem_sets; ++es)
4617 {
4618 // Debugging
4619 // libMesh::out << "Writing elemset variable values for elemset "
4620 // << es << ", elemset_id = " << elemset_ids[es]
4621 // << std::endl;
4622
4623 // We know num_elems_per_set because we called read_elemset_info() above.
4624 offset += (es > 0 ? num_elems_per_set[es-1] : 0);
4625 this->read_elemset(es, offset);
4626
4627 // For each variable in var_names, write the values for the
4628 // current elemset, if any.
4629 for (auto var : index_range(var_names))
4630 {
4631 // Debugging
4632 // libMesh::out << "Writing elemset variable values for var " << var << std::endl;
4633
4634 // If this var has no values on this elemset, go to the next one.
4635 if (!elemset_ids_in[var].count(elemset_ids[es]))
4636 continue;
4637
4638 // Otherwise, fill in this entry of the nodeset truth table.
4639 elemset_var_tab[es*var_names.size() + var] = 1;
4640
4641 // Data vector that will eventually be passed to exII::ex_put_var().
4642 std::vector<Real> elemset_var_vals(num_elems_per_set[es]);
4643
4644 // Get reference to the (elem_id, elemset_id) -> Real map for this variable.
4645 const auto & data_map = elemset_vals[var];
4646
4647 // Loop over entries in current elemset.
4648 for (int i=0; i<num_elems_per_set[es]; ++i)
4649 {
4650 // Here we convert Exodus elem ids to libMesh node ids
4651 // simply by subtracting 1. We should probably use the
4652 // exodus_elem_num_to_libmesh data structure for this,
4653 // but I don't think it is set up at the time when this
4654 // function is normally called.
4655 dof_id_type libmesh_elem_id = elemset_list[i + offset] - 1;
4656
4657 // Construct a key to look up values in data_map.
4658 std::pair<dof_id_type, elemset_id_type> key =
4659 std::make_pair(libmesh_elem_id, elemset_ids[es]);
4660
4661 // Debugging:
4662 // libMesh::out << "Searching for key = (" << key.first << ", " << key.second << ")" << std::endl;
4663
4664 // We require that the user provided either no values for
4665 // this (var, elemset) combination (in which case we don't
4666 // reach this point) or a value for _every_ elem in this
4667 // elemset for this var, so we use the libmesh_map_find()
4668 // macro to check for this.
4669 elemset_var_vals[i] = libmesh_map_find(data_map, key);
4670 } // end for (node in nodeset[ns])
4671
4672 // Write elemset values to Exodus file
4673 if (elemset_var_vals.size() > 0)
4674 {
4675 ex_err = exII::ex_put_var
4676 (ex_id,
4677 timestep,
4678 exII::EX_ELEM_SET,
4679 var + 1, // 1-based variable index of current variable
4680 elemset_ids[es],
4682 MappedOutputVector(elemset_var_vals, _single_precision).data());
4683 EX_CHECK_ERR(ex_err, "Error writing elemset vars.");
4684 }
4685 } // end for (var in var_names)
4686 } // end for (ns)
4687
4688 // Finally, write the elemset truth table to file.
4689 ex_err =
4690 exII::ex_put_truth_table(ex_id,
4691 exII::EX_ELEM_SET, // exII::ex_entity_type
4693 cast_int<int>(var_names.size()),
4694 elemset_var_tab.data());
4695 EX_CHECK_ERR(ex_err, "Error writing elemset var truth table.");
4696}
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 4085 of file exodusII_io_helper.C.

4086{
4087 LOG_SCOPE("write_elemsets()", "ExodusII_IO_Helper");
4088
4089 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4090 return;
4091
4092 // TODO: Add support for named elemsets
4093 // NamesData names_table(elemsets.size(), _max_name_length);
4094
4095 // We only need to write elemsets if the Mesh has an extra elem
4096 // integer called "elemset_code" defined on it.
4097 if (mesh.has_elem_integer("elemset_code"))
4098 {
4099 std::map<elemset_id_type, std::vector<int>> exodus_elemsets;
4100
4101 unsigned int elemset_index =
4102 mesh.get_elem_integer_index("elemset_code");
4103
4104 // Catch ids returned from MeshBase::get_elemsets() calls
4105 MeshBase::elemset_type set_ids;
4106 for (const auto & elem : mesh.element_ptr_range())
4107 {
4108 dof_id_type elemset_code =
4109 elem->get_extra_integer(elemset_index);
4110
4111 // Look up which element set ids (if any) this elemset_code corresponds to.
4112 mesh.get_elemsets(elemset_code, set_ids);
4113
4114 // Debugging
4115 // libMesh::out << "elemset_code = " << elemset_code << std::endl;
4116 // for (const auto & set_id : set_ids)
4117 // libMesh::out << set_id << " ";
4118 // libMesh::out << std::endl;
4119
4120 // Store this Elem id in every set to which it belongs.
4121 for (const auto & set_id : set_ids)
4122 exodus_elemsets[set_id].push_back(libmesh_elem_num_to_exodus[elem->id()]);
4123 }
4124
4125 // Debugging: print contents of exodus_elemsets map
4126 // for (const auto & [set_id, elem_ids] : exodus_elemsets)
4127 // {
4128 // libMesh::out << "elemset " << set_id << ": ";
4129 // for (const auto & elem_id : elem_ids)
4130 // libMesh::out << elem_id << " ";
4131 // libMesh::out << std::endl;
4132 // }
4133
4134 // Only continue if we actually had some elements in sets
4135 if (!exodus_elemsets.empty())
4136 {
4137 // Reserve space, loop over newly-created map, construct
4138 // exII::ex_set objects to be passed to exII::ex_put_sets(). Note:
4139 // we do non-const iteration since Exodus requires non-const pointers
4140 // to be passed to its APIs.
4141 std::vector<exII::ex_set> sets;
4142 sets.reserve(exodus_elemsets.size());
4143
4144 for (auto & [elem_set_id, ids_vec] : exodus_elemsets)
4145 {
4146 // TODO: Add support for named elemsets
4147 // names_table.push_back_entry(mesh.get_elemset_name(elem_set_id));
4148
4149 exII::ex_set & current_set = sets.emplace_back();
4150 current_set.id = elem_set_id;
4151 current_set.type = exII::EX_ELEM_SET;
4152 current_set.num_entry = ids_vec.size();
4153 current_set.num_distribution_factor = 0;
4154 current_set.entry_list = ids_vec.data();
4155 current_set.extra_list = nullptr; // extra_list is used for sidesets, not needed for elemsets
4156 current_set.distribution_factor_list = nullptr; // not used for elemsets
4157 }
4158
4159 // Sanity check: make sure the number of elemsets we already wrote to the header
4160 // matches the number of elemsets we just constructed by looping over the Mesh.
4161 libmesh_assert_msg(num_elem_sets == cast_int<int>(exodus_elemsets.size()),
4162 "Mesh has " << exodus_elemsets.size()
4163 << " elemsets, but header was written with num_elem_sets == " << num_elem_sets);
4164 libmesh_assert_msg(num_elem_sets == cast_int<int>(mesh.n_elemsets()),
4165 "mesh.n_elemsets() == " << mesh.n_elemsets()
4166 << ", but header was written with num_elem_sets == " << num_elem_sets);
4167
4168 ex_err = exII::ex_put_sets(ex_id, exodus_elemsets.size(), sets.data());
4169 EX_CHECK_ERR(ex_err, "Error writing elemsets");
4170
4171 // TODO: Add support for named elemsets
4172 // ex_err = exII::ex_put_names(ex_id, exII::EX_ELEM_SET, names_table.get_char_star_star());
4173 // EX_CHECK_ERR(ex_err, "Error writing elemset names");
4174 } // end if (!exodus_elemsets.empty())
4175 } // end if (mesh.has_elem_integer("elemset_code"))
4176}
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:487
std::set< elemset_id_type > elemset_type
Typedef for the "set" container used to store elemset ids.
Definition mesh_base.h:466

References _run_only_on_proc0, ex_err, ex_id, libMesh::MeshBase::get_elem_integer_index(), libMesh::MeshBase::get_elemsets(), libMesh::MeshBase::has_elem_integer(), 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 5286 of file exodusII_io_helper.C.

5287{
5288 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5289 return;
5290
5291 if (!values.empty())
5292 {
5293 ex_err = exII::ex_put_var
5294 (ex_id,
5295 timestep,
5296 exII::EX_GLOBAL,
5297 1, // var index
5298 0, // obj_id (not used)
5300 MappedOutputVector(values, _single_precision).data());
5301
5302 EX_CHECK_ERR(ex_err, "Error writing global values.");
5303
5304 this->update();
5305 }
5306}

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 5248 of file exodusII_io_helper.C.

5249{
5250 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5251 return;
5252
5253 // There may already be information records in the file (for
5254 // example, if we're appending) and in that case, according to the
5255 // Exodus documentation, writing more information records is not
5256 // supported.
5257 int num_info = inquire(*this, exII::EX_INQ_INFO, "Error retrieving the number of information records from file!");
5258 if (num_info > 0)
5259 {
5260 libMesh::err << "Warning! The Exodus file already contains information records.\n"
5261 << "Exodus does not support writing additional records in this situation."
5262 << std::endl;
5263 return;
5264 }
5265
5266 int num_records = cast_int<int>(records.size());
5267
5268 if (num_records > 0)
5269 {
5270 NamesData info(num_records, MAX_LINE_LENGTH);
5271
5272 // If an entry is longer than MAX_LINE_LENGTH characters it's not an error, we just
5273 // write the first MAX_LINE_LENGTH characters to the file.
5274 for (const auto & record : records)
5275 info.push_back_entry(record);
5276
5277 ex_err = exII::ex_put_info(ex_id, num_records, info.get_char_star_star());
5278 EX_CHECK_ERR(ex_err, "Error writing global values.");
5279
5280 this->update();
5281 }
5282}
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 2802 of file exodusII_io_helper.C.

2803{
2804 if ((_run_only_on_proc0) && (this->processor_id() != 0))
2805 return;
2806
2807 // Clear existing data from any previous calls.
2808 x.clear();
2809 y.clear();
2810 z.clear();
2811 node_num_map.clear();
2812
2813 // Reserve space in the nodal coordinate vectors. num_nodes is
2814 // exact, this just allows us to do away with one potentially
2815 // error-inducing loop index.
2816 x.reserve(num_nodes);
2817 y.reserve(num_nodes);
2818 z.reserve(num_nodes);
2819
2820 auto push_node = [this](const Point & p) {
2821 x.push_back(p(0) + _coordinate_offset(0));
2822
2823#if LIBMESH_DIM > 1
2824 y.push_back(p(1) + _coordinate_offset(1));
2825#else
2826 y.push_back(0.);
2827#endif
2828#if LIBMESH_DIM > 2
2829 z.push_back(p(2) + _coordinate_offset(2));
2830#else
2831 z.push_back(0.);
2832#endif
2833 };
2834
2835 // And in the node_num_map. If the user has set the
2836 // _set_unique_ids_from_maps flag, then we will write the Node
2837 // unique_ids to the node_num_map, otherwise we will just write a
2838 // trivial node_num_map, since in that we don't write the unique_id
2839 // information to the Exodus file. In other words, set the
2840 // _set_unique_ids_from_maps flag to true on both the reading and
2841 // writing ExodusII_IO objects if you want to preserve the
2842 // node_num_map information without actually renumbering the Nodes
2843 // in libmesh according to the node_num_map.
2844 //
2845 // One reason why you might not want to actually renumber the Nodes
2846 // in libmesh according to the node_num_map is that it can introduce
2847 // undesirable large "gaps" in the numbering, e.g. Nodes numbered
2848 // [0, 1, 1000, 10001] which is not ideal for the ReplicatedMesh
2849 // _nodes data structure, which stores the Nodes in a contiguous
2850 // array based on Node id.
2851
2852 // Let's skip the node_num_map in the discontinuous and add_sides
2853 // cases, since we're effectively duplicating nodes for the sake of
2854 // discontinuous visualization, so it isn't clear how to deal with
2855 // node_num_map here. This means that writing meshes in such a way
2856 // won't work with element numberings that have id "holes".
2857
2858 if (!use_discontinuous && !_add_sides)
2859 node_num_map.reserve(num_nodes);
2860
2861 // Clear out any previously-mapped node IDs.
2863
2864 if (!use_discontinuous)
2865 {
2866 for (const auto & node_ptr : mesh.node_ptr_range())
2867 {
2868 const Node & node = *node_ptr;
2869
2870 push_node(node);
2871
2872 // Fill in node_num_map entry with the proper (1-based) node
2873 // id, unless we're not going to be able to keep the map up
2874 // later. If the user has chosen to _set_unique_ids_from_maps,
2875 // then we fill up the node_num_map with (1-based) unique
2876 // ids rather than node ids.
2877 if (!_add_sides)
2878 {
2879 if (this->set_unique_ids_from_maps)
2880 node_num_map.push_back(node.unique_id() + 1);
2881 else
2882 node_num_map.push_back(node.id() + 1);
2883 }
2884
2885 // Also map the zero-based libmesh node id to the (1-based)
2886 // index in the node_num_map it corresponds to
2887 // (this is equivalent to the current size of the "x" vector,
2888 // so we just use x.size()). This map is used to look up
2889 // an Exodus Node id given a libMesh Node id, so it does
2890 // involve unique_ids.
2891 libmesh_node_num_to_exodus[ cast_int<int>(node.id()) ] = cast_int<int>(x.size());
2892 } // end for (node_ptr)
2893 }
2894 else // use_discontinuous
2895 {
2896 for (const auto & elem : mesh.active_element_ptr_range())
2897 for (const Node & node : elem->node_ref_range())
2898 {
2899 push_node(node);
2900
2901 // Let's skip the node_num_map in the discontinuous
2902 // case, since we're effectively duplicating nodes for
2903 // the sake of discontinuous visualization, so it isn't
2904 // clear how to deal with node_num_map here. This means
2905 // that writing discontinuous meshes won't work with
2906 // element numberings that have "holes".
2907 }
2908 }
2909
2910 if (_add_sides)
2911 {
2912 // To match the numbering of parallel-generated nodal solutions
2913 // on fake side nodes, we need to loop through elements from
2914 // earlier ranks first.
2915 std::vector<std::vector<const Elem *>>
2916 elems_by_pid(mesh.n_processors());
2917
2918 for (const auto & elem : mesh.active_element_ptr_range())
2919 elems_by_pid[elem->processor_id()].push_back(elem);
2920
2921 for (auto p : index_range(elems_by_pid))
2922 for (const Elem * elem : elems_by_pid[p])
2923 for (auto s : elem->side_index_range())
2924 {
2926 continue;
2927
2928 const std::vector<unsigned int> side_nodes =
2929 elem->nodes_on_side(s);
2930
2931 for (auto n : side_nodes)
2932 push_node(elem->point(n));
2933 }
2934
2935 // Node num maps just don't make sense if we're adding a bunch
2936 // of visualization nodes that are independent copies of the
2937 // same libMesh node.
2938 node_num_map.clear();
2939 }
2940
2941 ex_err = exII::ex_put_coord
2942 (ex_id,
2943 x.empty() ? nullptr : MappedOutputVector(x, _single_precision).data(),
2944 y.empty() ? nullptr : MappedOutputVector(y, _single_precision).data(),
2945 z.empty() ? nullptr : MappedOutputVector(z, _single_precision).data());
2946
2947 EX_CHECK_ERR(ex_err, "Error writing coordinates to Exodus file.");
2948
2949 if (!use_discontinuous && !_add_sides)
2950 {
2951 // Also write the (1-based) node_num_map to the file.
2952 ex_err = exII::ex_put_node_num_map(ex_id, node_num_map.data());
2953 EX_CHECK_ERR(ex_err, "Error writing node_num_map");
2954 }
2955}
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:40

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, num_nodes, libMesh::ParallelObject::processor_id(), libMesh::EquationSystems::redundant_added_side(), set_unique_ids_from_maps, libMesh::DofObject::unique_id(), x, y, and z.

◆ 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 5220 of file exodusII_io_helper.C.

5223{
5224 if ((_run_only_on_proc0) && (this->processor_id() != 0))
5225 return;
5226
5227 if (!values.empty())
5228 {
5229 libmesh_assert_equal_to(values.size(), std::size_t(num_nodes));
5230
5231 ex_err = exII::ex_put_var
5232 (ex_id,
5233 timestep,
5234 exII::EX_NODAL,
5235 var_id,
5236 1, // exII::ex_entity_id, not sure exactly what this is but in the ex_put_nodal_var.c shim, they pass 1
5237 num_nodes,
5238 MappedOutputVector(values, _single_precision).data());
5239
5240 EX_CHECK_ERR(ex_err, "Error writing nodal values.");
5241
5242 this->update();
5243 }
5244}

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 4473 of file exodusII_io_helper.C.

4478{
4479 LOG_SCOPE("write_nodeset_data()", "ExodusII_IO_Helper");
4480
4481 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4482 return;
4483
4484 // Write the nodeset variable names to file. This function should
4485 // only be called once for NODESET variables, repeated calls to
4486 // write_var_names() overwrites/changes the order of names that were
4487 // there previously, and will mess up any data that has already been
4488 // written.
4489 this->write_var_names(NODESET, var_names);
4490
4491 // For all nodesets, reads and fills in the arrays:
4492 // nodeset_ids
4493 // num_nodes_per_set
4494 // node_sets_node_index - starting index for each nodeset in the node_sets_node_list vector
4495 // node_sets_node_list
4496 // Note: we need these arrays so that we know what data to write
4497 this->read_all_nodesets();
4498
4499 // The "truth" table for nodeset variables. nset_var_tab is a
4500 // logically (num_node_sets x num_nset_var) integer array of 0s and
4501 // 1s indicating which nodesets a given nodeset variable is defined
4502 // on.
4503 std::vector<int> nset_var_tab(num_node_sets * var_names.size());
4504
4505 for (int ns=0; ns<num_node_sets; ++ns)
4506 {
4507 // The offset into the node_sets_node_list for the current nodeset
4508 int offset = node_sets_node_index[ns];
4509
4510 // For each variable in var_names, write the values for the
4511 // current nodeset, if any.
4512 for (auto var : index_range(var_names))
4513 {
4514 // If this var has no values on this nodeset, go to the next one.
4515 if (!node_boundary_ids[var].count(nodeset_ids[ns]))
4516 continue;
4517
4518 // Otherwise, fill in this entry of the nodeset truth table.
4519 nset_var_tab[ns*var_names.size() + var] = 1;
4520
4521 // Data vector that will eventually be passed to exII::ex_put_var().
4522 std::vector<Real> nset_var_vals(num_nodes_per_set[ns]);
4523
4524 // Get reference to the NodeBCTuple -> Real map for this variable.
4525 const auto & data_map = bc_vals[var];
4526
4527 // Loop over entries in current nodeset.
4528 for (int i=0; i<num_nodes_per_set[ns]; ++i)
4529 {
4530 // Here we convert Exodus node ids to libMesh node ids by
4531 // subtracting 1. We should probably use the
4532 // exodus_node_num_to_libmesh data structure for this, but
4533 // I don't think it is set up at the time when
4534 // write_nodeset_data() would normally be called.
4535 dof_id_type libmesh_node_id = node_sets_node_list[i + offset] - 1;
4536
4537 // Construct a key to look up values in data_map.
4539 std::make_tuple(libmesh_node_id, nodeset_ids[ns]);
4540
4541 // We require that the user provided either no values for
4542 // this (var, nodeset) combination (in which case we don't
4543 // reach this point) or a value for _every_ node in this
4544 // nodeset for this var, so we use the libmesh_map_find()
4545 // macro to check for this.
4546 nset_var_vals[i] = libmesh_map_find(data_map, key);
4547 } // end for (node in nodeset[ns])
4548
4549 // Write nodeset values to Exodus file
4550 if (nset_var_vals.size() > 0)
4551 {
4552 ex_err = exII::ex_put_var
4553 (ex_id,
4554 timestep,
4555 exII::EX_NODE_SET,
4556 var + 1, // 1-based variable index of current variable
4557 nodeset_ids[ns],
4559 MappedOutputVector(nset_var_vals, _single_precision).data());
4560 EX_CHECK_ERR(ex_err, "Error writing nodeset vars.");
4561 }
4562 } // end for (var in var_names)
4563 } // end for (ns)
4564
4565 // Finally, write the nodeset truth table.
4566 ex_err =
4567 exII::ex_put_truth_table(ex_id,
4568 exII::EX_NODE_SET,
4570 cast_int<int>(var_names.size()),
4571 nset_var_tab.data());
4572 EX_CHECK_ERR(ex_err, "Error writing nodeset var truth table.");
4573}
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 3797 of file exodusII_io_helper.C.

3798{
3799 LOG_SCOPE("write_nodesets()", "ExodusII_IO_Helper");
3800
3801 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3802 return;
3803
3804 // build_node_list() builds a sorted list of (node-id, bc-id) tuples
3805 // that is sorted by node-id, but we actually want it to be sorted
3806 // by bc-id, i.e. the second argument of the tuple.
3807 auto bc_tuples =
3809
3810 // We use std::stable_sort() here so that the entries within a
3811 // single nodeset remain sorted in node-id order, but now the
3812 // smallest boundary id's nodes appear first in the list, followed
3813 // by the second smallest, etc. That is, we are purposely doing two
3814 // different sorts here, with the first one being within the
3815 // build_node_list() call itself.
3816 std::stable_sort(bc_tuples.begin(), bc_tuples.end(),
3817 [](const BoundaryInfo::NodeBCTuple & t1,
3818 const BoundaryInfo::NodeBCTuple & t2)
3819 { return std::get<1>(t1) < std::get<1>(t2); });
3820
3821 std::vector<boundary_id_type> node_boundary_ids;
3822 mesh.get_boundary_info().build_node_boundary_ids(node_boundary_ids);
3823
3824 // Add any empty-but-named node boundary ids
3825 for (const auto & pair : mesh.get_boundary_info().get_nodeset_name_map())
3826 {
3827 const boundary_id_type id = pair.first;
3828
3829 if (std::find(node_boundary_ids.begin(),
3830 node_boundary_ids.end(), id)
3831 == node_boundary_ids.end())
3832 node_boundary_ids.push_back(id);
3833 }
3834
3835 // Write out the nodeset names, but only if there is something to write
3836 if (node_boundary_ids.size() > 0)
3837 {
3838 NamesData names_table(node_boundary_ids.size(), _max_name_length);
3839
3840 // Vectors to be filled and passed to exII::ex_put_concat_sets()
3841 // Use existing class members and avoid variable shadowing.
3842 nodeset_ids.clear();
3843 num_nodes_per_set.clear();
3844 num_node_df_per_set.clear();
3845 node_sets_node_index.clear();
3846 node_sets_node_list.clear();
3847
3848 // Pre-allocate space
3849 nodeset_ids.reserve(node_boundary_ids.size());
3850 num_nodes_per_set.reserve(node_boundary_ids.size());
3851 num_node_df_per_set.resize(node_boundary_ids.size()); // all zeros
3852 node_sets_node_index.reserve(node_boundary_ids.size());
3853 node_sets_node_list.reserve(bc_tuples.size());
3854
3855 // Assign entries to node_sets_node_list, keeping track of counts as we go.
3856 std::map<boundary_id_type, unsigned int> nodeset_counts;
3857 for (auto id : node_boundary_ids)
3858 nodeset_counts[id] = 0;
3859
3860 for (const auto & t : bc_tuples)
3861 {
3862 const dof_id_type & node_id = std::get<0>(t) + 1; // Note: we use 1-based node ids in Exodus!
3863 const boundary_id_type & nodeset_id = std::get<1>(t);
3864 node_sets_node_list.push_back(node_id);
3865 nodeset_counts[nodeset_id] += 1;
3866 }
3867
3868 // Fill in other indexing vectors needed by Exodus
3869 unsigned int running_sum = 0;
3870 for (const auto & pr : nodeset_counts)
3871 {
3872 nodeset_ids.push_back(pr.first);
3873 num_nodes_per_set.push_back(pr.second);
3874 node_sets_node_index.push_back(running_sum);
3875 names_table.push_back_entry(mesh.get_boundary_info().get_nodeset_name(pr.first));
3876 running_sum += pr.second;
3877 }
3878
3879 // Fill in an exII::ex_set_specs object which can then be passed to
3880 // the ex_put_concat_sets() function.
3881 exII::ex_set_specs set_data = {};
3882 set_data.sets_ids = nodeset_ids.data();
3883 set_data.num_entries_per_set = num_nodes_per_set.data();
3884 set_data.num_dist_per_set = num_node_df_per_set.data(); // zeros
3885 set_data.sets_entry_index = node_sets_node_index.data();
3886 set_data.sets_dist_index = node_sets_node_index.data(); // dummy value
3887 set_data.sets_entry_list = node_sets_node_list.data();
3888
3889 // Write all nodesets together.
3890 ex_err = exII::ex_put_concat_sets(ex_id, exII::EX_NODE_SET, &set_data);
3891 EX_CHECK_ERR(ex_err, "Error writing concatenated nodesets");
3892
3893 // Write out the nodeset names
3894 ex_err = exII::ex_put_names(ex_id, exII::EX_NODE_SET, names_table.get_char_star_star());
3895 EX_CHECK_ERR(ex_err, "Error writing nodeset names");
3896 }
3897}
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 4181 of file exodusII_io_helper.C.

4187{
4188 LOG_SCOPE("write_sideset_data()", "ExodusII_IO_Helper");
4189
4190 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4191 return;
4192
4193 // Write the sideset variable names to file. This function should
4194 // only be called once for SIDESET variables, repeated calls to
4195 // write_var_names overwrites/changes the order of names that were
4196 // there previously, and will mess up any data that has already been
4197 // written.
4198 this->write_var_names(SIDESET, var_names);
4199
4200 // I hope that we are allowed to call read_sideset_info() even
4201 // though we are in the middle of writing? It seems to work provided
4202 // that you have already written the mesh itself... read_sideset_info()
4203 // fills in the following data members:
4204 // .) num_side_sets
4205 // .) ss_ids
4206 this->read_sideset_info();
4207
4208 // Write "truth" table for sideset variables. The function
4209 // exII::ex_put_variable_param() must be called before
4210 // exII::ex_put_truth_table(). For us, this happens during the call
4211 // to ExodusII_IO_Helper::write_var_names(). sset_var_tab is a logically
4212 // (num_side_sets x num_sset_var) integer array of 0s and 1s
4213 // indicating which sidesets a given sideset variable is defined on.
4214 std::vector<int> sset_var_tab(num_side_sets * var_names.size());
4215
4216 // We now call read_sideset() once per sideset and write any sideset
4217 // variable values which are defined there.
4218 int offset=0;
4219 for (int ss=0; ss<num_side_sets; ++ss)
4220 {
4221 // We don't know num_sides_per_set for each set until we call
4222 // read_sideset(). The values for each sideset are stored (using
4223 // the offsets) into the 'elem_list' and 'side_list' arrays of
4224 // this class.
4225 offset += (ss > 0 ? num_sides_per_set[ss-1] : 0);
4226 this->read_sideset(ss, offset);
4227
4228 // For each variable in var_names, write the values for the
4229 // current sideset, if any.
4230 for (auto var : index_range(var_names))
4231 {
4232 // If this var has no values on this sideset, go to the next one.
4233 if (!side_ids[var].count(ss_ids[ss]))
4234 continue;
4235
4236 // Otherwise, fill in this entry of the sideset truth table.
4237 sset_var_tab[ss*var_names.size() + var] = 1;
4238
4239 // Data vector that will eventually be passed to exII::ex_put_var().
4240 std::vector<Real> sset_var_vals(num_sides_per_set[ss]);
4241
4242 // Get reference to the BCTuple -> Real map for this variable.
4243 const auto & data_map = bc_vals[var];
4244
4245 // Loop over elem_list, side_list entries in current sideset.
4246 for (int i=0; i<num_sides_per_set[ss]; ++i)
4247 {
4248 // Get elem_id and side_id from the respective lists that
4249 // are filled in by calling read_sideset().
4250 //
4251 // Note: these are Exodus-specific ids, so we have to convert them
4252 // to libmesh ids, as that is what will be in the bc_tuples.
4253 //
4254 // TODO: we should probably consult the exodus_elem_num_to_libmesh
4255 // mapping in order to figure out which libmesh element id 'elem_id'
4256 // actually corresponds to here, instead of just assuming it will be
4257 // off by one. Unfortunately that data structure does not seem to
4258 // be used at the moment. If we assume that write_sideset_data() is
4259 // always called following write(), then this should be a fairly safe
4260 // assumption...
4261 dof_id_type elem_id = elem_list[i + offset] - 1;
4262 unsigned int side_id = side_list[i + offset] - 1;
4263
4264 // Sanity check: make sure that the "off by one"
4265 // assumption we used above to set 'elem_id' is valid.
4266 libmesh_error_msg_if
4267 (libmesh_map_find(libmesh_elem_num_to_exodus, cast_int<int>(elem_id)) !=
4268 cast_int<dof_id_type>(elem_list[i + offset]),
4269 "Error mapping Exodus elem id to libmesh elem id.");
4270
4271 // Map from Exodus side ids to libmesh side ids.
4272 const auto & conv = get_conversion(mesh.elem_ptr(elem_id)->type());
4273
4274 // Map from Exodus side ids to libmesh side ids.
4275 unsigned int converted_side_id = conv.get_side_map(side_id);
4276
4277 // Construct a key so we can quickly see whether there is any
4278 // data for this variable in the map.
4279 BoundaryInfo::BCTuple key = std::make_tuple
4280 (elem_id,
4281 converted_side_id,
4282 ss_ids[ss]);
4283
4284 // Find the data for this (elem,side,id) tuple. Throw an
4285 // error if not found. Then store value in vector which
4286 // will be passed to Exodus.
4287 sset_var_vals[i] = libmesh_map_find(data_map, key);
4288 } // end for (i)
4289
4290 // As far as I can tell, there is no "concat" version of writing
4291 // sideset data, you have to call ex_put_sset_var() once per (variable,
4292 // sideset) pair.
4293 if (sset_var_vals.size() > 0)
4294 {
4295 ex_err = exII::ex_put_var
4296 (ex_id,
4297 timestep,
4298 exII::EX_SIDE_SET,
4299 var + 1, // 1-based variable index of current variable
4300 ss_ids[ss],
4302 MappedOutputVector(sset_var_vals, _single_precision).data());
4303 EX_CHECK_ERR(ex_err, "Error writing sideset vars.");
4304 }
4305 } // end for (var)
4306 } // end for (ss)
4307
4308 // Finally, write the sideset truth table.
4309 ex_err =
4310 exII::ex_put_truth_table(ex_id,
4311 exII::EX_SIDE_SET,
4313 cast_int<int>(var_names.size()),
4314 sset_var_tab.data());
4315 EX_CHECK_ERR(ex_err, "Error writing sideset var truth table.");
4316}
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 3673 of file exodusII_io_helper.C.

3674{
3675 LOG_SCOPE("write_sidesets()", "ExodusII_IO_Helper");
3676
3677 if ((_run_only_on_proc0) && (this->processor_id() != 0))
3678 return;
3679
3680 // Maps from sideset id to lists of corresponding element ids and side ids
3681 std::map<int, std::vector<int>> elem_lists;
3682 std::map<int, std::vector<int>> side_lists;
3683 std::set<boundary_id_type> side_boundary_ids;
3684
3685 {
3686 // Accumulate the vectors to pass into ex_put_side_set
3687 // build_side_lists() returns a vector of (elem, side, bc) tuples.
3688 for (const auto & t : mesh.get_boundary_info().build_side_list())
3689 {
3690 std::vector<const Elem *> family;
3691#ifdef LIBMESH_ENABLE_AMR
3696 mesh.elem_ref(std::get<0>(t)).active_family_tree_by_side(family, std::get<1>(t), false);
3697#else
3698 family.push_back(mesh.elem_ptr(std::get<0>(t)));
3699#endif
3700
3701 for (const auto & f : family)
3702 {
3703 const auto & conv = get_conversion(mesh.elem_ptr(f->id())->type());
3704
3705 // Use the libmesh to exodus data structure map to get the proper sideset IDs
3706 // The data structure contains the "collapsed" contiguous ids
3707 elem_lists[std::get<2>(t)].push_back(libmesh_elem_num_to_exodus[f->id()]);
3708 side_lists[std::get<2>(t)].push_back(conv.get_inverse_side_map(std::get<1>(t)));
3709 }
3710 }
3711
3712 std::vector<boundary_id_type> tmp;
3714 side_boundary_ids.insert(tmp.begin(), tmp.end());
3715 }
3716
3717 {
3718 // add data for shell faces, if needed
3719
3720 // Accumulate the vectors to pass into ex_put_side_set
3721 for (const auto & t : mesh.get_boundary_info().build_shellface_list())
3722 {
3723 std::vector<const Elem *> family;
3724#ifdef LIBMESH_ENABLE_AMR
3729 mesh.elem_ref(std::get<0>(t)).active_family_tree_by_side(family, std::get<1>(t), false);
3730#else
3731 family.push_back(mesh.elem_ptr(std::get<0>(t)));
3732#endif
3733
3734 for (const auto & f : family)
3735 {
3736 const auto & conv = get_conversion(mesh.elem_ptr(f->id())->type());
3737
3738 // Use the libmesh to exodus data structure map to get the proper sideset IDs
3739 // The data structure contains the "collapsed" contiguous ids
3740 elem_lists[std::get<2>(t)].push_back(libmesh_elem_num_to_exodus[f->id()]);
3741 side_lists[std::get<2>(t)].push_back(conv.get_inverse_shellface_map(std::get<1>(t)));
3742 }
3743 }
3744
3745 std::vector<boundary_id_type> tmp;
3747 side_boundary_ids.insert(tmp.begin(), tmp.end());
3748 }
3749
3750 // Add any empty-but-named side boundary ids
3751 for (const auto & pr : mesh.get_boundary_info().get_sideset_name_map())
3752 side_boundary_ids.insert(pr.first);
3753
3754 // Write out the sideset names, but only if there is something to write
3755 if (side_boundary_ids.size() > 0)
3756 {
3757 NamesData names_table(side_boundary_ids.size(), _max_name_length);
3758
3759 std::vector<exII::ex_set> sets(side_boundary_ids.size());
3760
3761 // Loop over "side_boundary_ids" and "sets" simultaneously
3762 for (auto [i, it] = std::tuple{0u, side_boundary_ids.begin()}; i<sets.size(); ++i, ++it)
3763 {
3764 boundary_id_type ss_id = *it;
3765 names_table.push_back_entry(mesh.get_boundary_info().get_sideset_name(ss_id));
3766
3767 sets[i].id = ss_id;
3768 sets[i].type = exII::EX_SIDE_SET;
3769 sets[i].num_distribution_factor = 0;
3770 sets[i].distribution_factor_list = nullptr;
3771
3772 if (const auto elem_it = elem_lists.find(ss_id);
3773 elem_it == elem_lists.end())
3774 {
3775 sets[i].num_entry = 0;
3776 sets[i].entry_list = nullptr;
3777 sets[i].extra_list = nullptr;
3778 }
3779 else
3780 {
3781 sets[i].num_entry = elem_it->second.size();
3782 sets[i].entry_list = elem_it->second.data();
3783 sets[i].extra_list = libmesh_map_find(side_lists, ss_id).data();
3784 }
3785 }
3786
3787 ex_err = exII::ex_put_sets(ex_id, side_boundary_ids.size(), sets.data());
3788 EX_CHECK_ERR(ex_err, "Error writing sidesets");
3789
3790 ex_err = exII::ex_put_names(ex_id, exII::EX_SIDE_SET, names_table.get_char_star_star());
3791 EX_CHECK_ERR(ex_err, "Error writing sideset names");
3792 }
3793}
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:2194

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 4062 of file exodusII_io_helper.C.

4063{
4064 if ((_run_only_on_proc0) && (this->processor_id() != 0))
4065 return;
4066
4068 {
4069 float cast_time = float(time);
4070 ex_err = exII::ex_put_time(ex_id, timestep, &cast_time);
4071 }
4072 else
4073 {
4074 double cast_time = double(time);
4075 ex_err = exII::ex_put_time(ex_id, timestep, &cast_time);
4076 }
4077 EX_CHECK_ERR(ex_err, "Error writing timestep.");
4078
4079 this->update();
4080}

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 2238 of file exodusII_io_helper.C.

2240{
2241 switch (type)
2242 {
2243 case NODAL:
2244 this->write_var_names_impl("n", num_nodal_vars, names);
2245 break;
2246 case ELEMENTAL:
2247 this->write_var_names_impl("e", num_elem_vars, names);
2248 break;
2249 case GLOBAL:
2250 this->write_var_names_impl("g", num_global_vars, names);
2251 break;
2252 case SIDESET:
2253 {
2254 // Note: calling this function *sets* num_sideset_vars to the
2255 // number of entries in the 'names' vector, num_sideset_vars
2256 // does not already need to be set before calling this.
2257 this->write_var_names_impl("s", num_sideset_vars, names);
2258 break;
2259 }
2260 case NODESET:
2261 {
2262 this->write_var_names_impl("m", num_nodeset_vars, names);
2263 break;
2264 }
2265 case ELEMSET:
2266 {
2267 this->write_var_names_impl("t", num_elemset_vars, names);
2268 break;
2269 }
2270 default:
2271 libmesh_error_msg("Unrecognized ExodusVarType " << type);
2272 }
2273}
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 2278 of file exodusII_io_helper.C.

2281{
2282 // Update the count variable so that it's available to other parts of the class.
2283 count = cast_int<int>(names.size());
2284
2285 // Write that number of variables to the file.
2286 ex_err = exII::ex_put_var_param(ex_id, var_type, count);
2287 EX_CHECK_ERR(ex_err, "Error setting number of vars.");
2288
2289 // Nemesis doesn't like trying to write nodal variable names in
2290 // files with no nodes.
2291 if (!this->num_nodes)
2292 return;
2293
2294 if (count > 0)
2295 {
2296 NamesData names_table(count, _max_name_length);
2297
2298 // Store the input names in the format required by Exodus.
2299 for (int i=0; i != count; ++i)
2300 {
2301 if(names[i].length() > _max_name_length)
2302 libmesh_warning(
2303 "*** Warning, Exodus variable name \"" <<
2304 names[i] << "\" too long (current max " <<
2305 _max_name_length << "/" << libmesh_max_str_length <<
2306 " characters). Name will be truncated. ");
2307 names_table.push_back_entry(names[i]);
2308 }
2309
2310 if (verbose)
2311 {
2312 libMesh::out << "Writing variable name(s) to file: " << std::endl;
2313 for (int i=0; i != count; ++i)
2314 libMesh::out << names_table.get_char_star(i) << std::endl;
2315 }
2316
2317 ex_err = exII::ex_put_var_names(ex_id,
2318 var_type,
2319 count,
2320 names_table.get_char_star_star()
2321 );
2322
2323 EX_CHECK_ERR(ex_err, "Error writing variable names.");
2324 }
2325}

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: