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

The Nemesis_IO class implements reading parallel meshes in the Nemesis file format from Sandia National Labs. More...

#include <nemesis_io.h>

Inheritance diagram for libMesh::Nemesis_IO:
[legend]

Public Member Functions

 Nemesis_IO (MeshBase &mesh, bool single_precision=false)
 Constructor.
 
 Nemesis_IO (const MeshBase &mesh, bool single_precision=false)
 Constructor.
 
virtual ~Nemesis_IO ()
 Destructor.
 
virtual void read (const std::string &base_filename) override
 Implements reading the mesh from several different files.
 
virtual void write (const std::string &base_filename) override
 This method implements writing a mesh to a specified file.
 
void write_timestep (const std::string &fname, const EquationSystems &es, const int timestep, const Real time)
 Write one timestep's worth of the solution.
 
void set_output_variables (const std::vector< std::string > &output_variables, bool allow_empty=true)
 Specify the list of variables which should be included in the output (whitelist) If empty, then all variables will be present in the output.
 
virtual void write_nodal_data (const std::string &fname, const std::vector< Number > &soln, const std::vector< std::string > &names) override
 Output a nodal solution from data in soln.
 
virtual void write_nodal_data (const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names) override
 Output a nodal solution from EquationSystems current_local_solutions.
 
virtual void write_nodal_data (const std::string &fname, const NumericVector< Number > &parallel_soln, const std::vector< std::string > &names) override
 Output a nodal solution in parallel, without localizing the soln vector.
 
void write_element_data (const EquationSystems &es)
 Write out element solution in parallel, without localizing the solution vector.
 
void verbose (bool set_verbosity)
 Set the flag indicating if we should be verbose.
 
void write_complex_magnitude (bool val)
 Set the flag indicating whether the complex modulus should be written when complex numbers are enabled.
 
void write_global_data (const std::vector< Number > &, const std::vector< std::string > &)
 Write out global variables.
 
void write_information_records (const std::vector< std::string > &)
 Write out information records.
 
void append (bool val)
 If true, this flag will cause the Nemesis_IO object to attempt to open an existing file for writing, rather than creating a new file.
 
const std::vector< std::string > & get_elem_var_names ()
 Return list of the elemental variable names.
 
const std::vector< std::string > & get_nodal_var_names ()
 Return list of the nodal variable names.
 
const std::vector< std::string > & get_global_var_names ()
 Return list of the global variable names.
 
const std::vector< Real > & get_time_steps ()
 
int get_num_time_steps ()
 
void copy_nodal_solution (System &system, std::string system_var_name, std::string exodus_var_name, unsigned int timestep=1)
 If we read in a nodal solution while reading in a mesh, we can attempt to copy that nodal solution into an EquationSystems object.
 
void copy_elemental_solution (System &system, std::string system_var_name, std::string exodus_var_name, unsigned int timestep=1)
 If we read in a elemental solution while reading in a mesh, we can attempt to copy that elemental solution into an EquationSystems object.
 
void copy_scalar_solution (System &system, std::vector< std::string > system_var_names, std::vector< std::string > exodus_var_names, unsigned int timestep=1)
 Copy global variables into scalar variables of a System object.
 
void read_global_variable (std::vector< std::string > global_var_names, unsigned int timestep, std::vector< Real > &global_values)
 Given a vector of global variables and a time step, returns the values of the global variable at the corresponding time step index.
 
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.
 
Nemesis_IO_Helperget_nemio_helper ()
 Return a reference to the Nemesis_IO_Helper object.
 
bool is_parallel_format () const
 Returns true iff this mesh file format and input class are parallelized, so that all processors can read their share of the data at once.
 
virtual void write_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
 This method implements writing a mesh with data to a specified file where the data is taken from the EquationSystems object.
 
virtual void write_discontinuous_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
 This method implements writing a mesh with discontinuous data to a specified file where the data is taken from the EquationSystems object.
 
virtual void write_nodal_data_discontinuous (const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
 This method implements writing a mesh with discontinuous data to a specified file where the nodal data and variables names are provided.
 
unsigned intascii_precision ()
 Return/set the precision to use when writing ASCII files.
 
const Parallel::Communicatorcomm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Protected Member Functions

MeshBasemesh ()
 
void set_n_partitions (unsigned int n_parts)
 Sets the number of partitions in the mesh.
 
void skip_comment_lines (std::istream &in, const char comment_start)
 Reads input from in, skipping all the lines that start with the character comment_start.
 
const MeshBasemesh () const
 
virtual bool get_add_sides ()
 

Protected Attributes

std::vector< bool > elems_of_dimension
 A vector of bools describing what dimension elements have been encountered when reading a mesh.
 
const bool _is_parallel_format
 Flag specifying whether this format is parallel-capable.
 
const bool _serial_only_needed_on_proc_0
 Flag specifying whether this format can be written by only serializing the mesh to processor zero.
 
const Parallel::Communicator_communicator
 

Private Member Functions

void assert_symmetric_cmaps ()
 
void prepare_to_write_nodal_data (const std::string &fname, const std::vector< std::string > &names)
 Helper function containing code shared between the two different versions of write_nodal_data which take std::vector and NumericVector, respectively.
 

Private Attributes

std::unique_ptr< Nemesis_IO_Helpernemhelper
 
int _timestep
 Keeps track of the current timestep index being written.
 
bool _verbose
 Controls whether extra debugging information is printed to the screen or not.
 
bool _append
 Default false.
 
std::vector< std::string > _output_variables
 The names of the variables to be output.
 
bool _allow_empty_variables
 If true, _output_variables is allowed to remain empty.
 
MeshBase_obj
 A pointer to a non-const object object.
 
const bool _is_parallel_format
 Flag specifying whether this format is parallel-capable.
 
unsigned int _ascii_precision
 Precision to use when writing ASCII files.
 

Detailed Description

The Nemesis_IO class implements reading parallel meshes in the Nemesis file format from Sandia National Labs.

Nemesis files are essentially in the Exodus format plus some additional information. All the Nemesis files for a single mesh have the same basename, e.g. cylinder.e, followed by ".size.rank", where size is the total number of files the Mesh is split into and rank is the ID of the processor's elements that were written to the file.

Author
John Peterson
Date
2008

Definition at line 51 of file nemesis_io.h.

Constructor & Destructor Documentation

◆ Nemesis_IO() [1/2]

libMesh::Nemesis_IO::Nemesis_IO ( MeshBase mesh,
bool  single_precision = false 
)
explicit

Constructor.

Takes a writable reference to a mesh object. This is the constructor required to read a mesh.

Definition at line 95 of file nemesis_io.C.

96 :
97 MeshInput<MeshBase> (mesh, /*is_parallel_format=*/true),
98 MeshOutput<MeshBase> (mesh, /*is_parallel_format=*/true),
100#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
101 nemhelper(std::make_unique<Nemesis_IO_Helper>(*this, false, single_precision)),
102 _timestep(1),
103#endif
104 _verbose (false),
105 _append(false),
107{
108 // if !LIBMESH_HAVE_EXODUS_API, we didn't use this
109 libmesh_ignore(single_precision);
110}
std::unique_ptr< Nemesis_IO_Helper > nemhelper
Definition nemesis_io.h:263
bool _allow_empty_variables
If true, _output_variables is allowed to remain empty.
Definition nemesis_io.h:302
bool _append
Default false.
Definition nemesis_io.h:281
int _timestep
Keeps track of the current timestep index being written.
Definition nemesis_io.h:269
bool _verbose
Controls whether extra debugging information is printed to the screen or not.
Definition nemesis_io.h:275
ParallelObject(const Parallel::Communicator &comm_in)
Constructor.
void libmesh_ignore(const Args &...)
template class LIBMESH_EXPORT MeshOutput< MeshBase >

References libMesh::libmesh_ignore().

◆ Nemesis_IO() [2/2]

libMesh::Nemesis_IO::Nemesis_IO ( const MeshBase mesh,
bool  single_precision = false 
)
explicit

Constructor.

Takes a const reference to a mesh object. This constructor is acceptable to write meshes.

Definition at line 114 of file nemesis_io.C.

115 :
116 MeshInput<MeshBase> (),
117 MeshOutput<MeshBase> (mesh, /*is_parallel_format=*/true),
119#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
120 nemhelper(std::make_unique<Nemesis_IO_Helper>(*this, false, single_precision)),
121 _timestep(1),
122#endif
123 _verbose (false),
124 _append(false),
126{
127 // if !LIBMESH_HAVE_EXODUS_API, we didn't use this
128 libmesh_ignore(single_precision);
129}

References libMesh::libmesh_ignore().

◆ ~Nemesis_IO()

libMesh::Nemesis_IO::~Nemesis_IO ( )
virtualdefault

Destructor.

Member Function Documentation

◆ append()

void libMesh::Nemesis_IO::append ( bool  val)

If true, this flag will cause the Nemesis_IO object to attempt to open an existing file for writing, rather than creating a new file.

Obviously this will only work if the file already exists.

Definition at line 162 of file nemesis_io.C.

163{
164 _append = val;
165}

References _append.

◆ ascii_precision()

unsigned int & libMesh::MeshOutput< MeshBase >::ascii_precision ( )
inlineinherited

Return/set the precision to use when writing ASCII files.

By default we use numeric_limits<Real>::max_digits10, which should be enough to write out to ASCII and get the exact same Real back when reading in.

Definition at line 160 of file mesh_output.h.

270{
271 return _ascii_precision;
272}
unsigned int _ascii_precision
Precision to use when writing ASCII files.

◆ assert_symmetric_cmaps()

void libMesh::Nemesis_IO::assert_symmetric_cmaps ( )
private

Definition at line 178 of file nemesis_io.C.

179{
180#ifndef NDEBUG
181#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
182 // We expect the communication maps to be symmetric - e.g. if processor i thinks it
183 // communicates with processor j, then processor j should also be expecting to
184 // communicate with i. We can assert that here easily enough with an alltoall,
185 // but let's only do it when not in optimized mode to limit unnecessary communication.
186 {
187 std::vector<unsigned char> pid_send_partner (this->n_processors(), 0);
188
189 // strictly speaking, we should expect to communicate with ourself...
190 pid_send_partner[this->processor_id()] = 1;
191
192 // mark each processor id we reference with a node cmap
193 for (unsigned int cmap=0; cmap<to_uint(nemhelper->num_node_cmaps); cmap++)
194 {
195 libmesh_assert_less (nemhelper->node_cmap_ids[cmap], this->n_processors());
196
197 pid_send_partner[nemhelper->node_cmap_ids[cmap]] = 1;
198 }
199
200 // Copy the send pairing so we can catch the receive paring and
201 // test for equality
202 const std::vector<unsigned char> pid_recv_partner (pid_send_partner);
203
204 this->comm().alltoall (pid_send_partner);
205
206 libmesh_assert (pid_send_partner == pid_recv_partner);
207 }
208#endif
209#endif
210}
void alltoall(std::vector< T, A > &r) const
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
libmesh_assert(ctx)

References libMesh::Parallel::Communicator::alltoall(), libMesh::ParallelObject::comm(), libMesh::libmesh_assert(), libMesh::ParallelObject::n_processors(), nemhelper, and libMesh::ParallelObject::processor_id().

Referenced by prepare_to_write_nodal_data(), read(), and write().

◆ 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(), 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(), libMesh::ExodusII_IO_Helper::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(), 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().

◆ copy_elemental_solution()

void libMesh::Nemesis_IO::copy_elemental_solution ( System system,
std::string  system_var_name,
std::string  exodus_var_name,
unsigned int  timestep = 1 
)

If we read in a elemental solution while reading in a mesh, we can attempt to copy that elemental solution into an EquationSystems object.

Definition at line 1737 of file nemesis_io.C.

1741{
1742 parallel_object_only();
1743
1744 const unsigned int var_num = system.variable_number(system_var_name);
1745 const auto & var_type = system.variable_type(var_num);
1746 libmesh_error_msg_if(!EquationSystems::is_elemental_data_fe_type(var_type) ||
1748 "Error! Trying to copy elemental solution into a variable that is not scalar elemental data.");
1749
1750 const MeshBase & mesh = MeshInput<MeshBase>::mesh();
1751
1752 // Map from element ID to elemental variable value. We need to use
1753 // a map here rather than a vector (e.g. elem_var_values) since the
1754 // libmesh element numbering can contain "holes". This is the case
1755 // if we are reading elemental var values from an adaptively refined
1756 // mesh that has not been sequentially renumbered.
1757 std::map<dof_id_type, Real> elem_var_value_map;
1758
1759 libmesh_error_msg_if(!nemhelper->opened_for_reading,
1760 "ERROR, Nemesis file must be opened for reading before copying an elemental solution!");
1761
1762 nemhelper->read_elemental_var_values(exodus_var_name, timestep, elem_var_value_map);
1763
1764 std::map<dof_id_type, Real>::iterator
1765 it = elem_var_value_map.begin(),
1766 end = elem_var_value_map.end();
1767
1768 for (; it!=end; ++it)
1769 {
1770 const Elem * elem = mesh.query_elem_ptr(it->first);
1771
1772 if (elem && elem->n_comp(system.number(), var_num) > 0)
1773 {
1774 dof_id_type dof_index = elem->dof_number(system.number(), var_num, 0);
1775 libmesh_assert(system.get_dof_map().local_index(dof_index));
1776 system.solution->set (dof_index, it->second);
1777 }
1778 }
1779
1780 system.solution->close();
1781 system.update();
1782
1783 parallel_object_only();
1784}
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
static bool is_elemental_data_fe_type(const FEType &type)
static FEFieldType field_type(const FEType &fe_type)
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
uint8_t dof_id_type
Definition id_types.h:67

References libMesh::DofObject::dof_number(), libMesh::FEInterface::field_type(), libMesh::System::get_dof_map(), libMesh::EquationSystems::is_elemental_data_fe_type(), libMesh::libmesh_assert(), libMesh::DofMap::local_index(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshInput< MT >::mesh(), libMesh::DofObject::n_comp(), nemhelper, libMesh::System::number(), libMesh::MeshBase::query_elem_ptr(), libMesh::System::solution, libMesh::TYPE_VECTOR, libMesh::System::update(), libMesh::System::variable_number(), and libMesh::System::variable_type().

Referenced by MeshInputTest::testSingleElementImpl().

◆ copy_nodal_solution()

void libMesh::Nemesis_IO::copy_nodal_solution ( System system,
std::string  system_var_name,
std::string  exodus_var_name,
unsigned int  timestep = 1 
)

If we read in a nodal solution while reading in a mesh, we can attempt to copy that nodal solution into an EquationSystems object.

Definition at line 1704 of file nemesis_io.C.

1708{
1709 libmesh_error_msg_if(!nemhelper->opened_for_reading,
1710 "ERROR, Nemesis file must be opened for reading before copying a nodal solution!");
1711
1712 nemhelper->read_nodal_var_values(exodus_var_name, timestep);
1713
1714 const unsigned int var_num = system.variable_number(system_var_name);
1715
1716 for (auto p : nemhelper->nodal_var_values)
1717 {
1718 dof_id_type i = p.first;
1719 const Node * node = MeshInput<MeshBase>::mesh().node_ptr(i);
1720
1721 if (node && node->n_comp(system.number(), var_num) > 0)
1722 {
1723 dof_id_type dof_index = node->dof_number(system.number(), var_num, 0);
1724
1725 // If the dof_index is local to this processor, set the value
1726 if (system.get_dof_map().local_index(dof_index))
1727 system.solution->set (dof_index, p.second);
1728 }
1729 }
1730
1731 system.solution->close();
1732 system.update();
1733}

References libMesh::DofObject::dof_number(), libMesh::System::get_dof_map(), libMesh::DofMap::local_index(), libMesh::MeshInput< MT >::mesh(), libMesh::DofObject::n_comp(), nemhelper, libMesh::System::number(), libMesh::System::solution, libMesh::System::update(), and libMesh::System::variable_number().

Referenced by WriteVecAndScalar::testWriteNemesis().

◆ copy_scalar_solution()

void libMesh::Nemesis_IO::copy_scalar_solution ( System system,
std::vector< std::string >  system_var_names,
std::vector< std::string >  exodus_var_names,
unsigned int  timestep = 1 
)

Copy global variables into scalar variables of a System object.

Definition at line 1788 of file nemesis_io.C.

1792{
1793 libmesh_error_msg_if(!nemhelper->opened_for_reading,
1794 "ERROR, Nemesis file must be opened for reading before copying a scalar solution!");
1795
1796 libmesh_error_msg_if(system_var_names.size() != exodus_var_names.size(),
1797 "ERROR, the number of system_var_names must match exodus_var_names.");
1798
1799 std::vector<Real> values_from_exodus;
1800 read_global_variable(exodus_var_names, timestep, values_from_exodus);
1801
1802 if (system.processor_id() == (system.n_processors()-1))
1803 {
1804 const DofMap & dof_map = system.get_dof_map();
1805
1806 for (auto i : index_range(system_var_names))
1807 {
1808 const unsigned int var_num = system.variable_scalar_number(system_var_names[i], 0);
1809
1810 std::vector<dof_id_type> SCALAR_dofs;
1811 dof_map.SCALAR_dof_indices(SCALAR_dofs, var_num);
1812
1813 system.solution->set (SCALAR_dofs[0], values_from_exodus[i]);
1814 }
1815 }
1816
1817 system.solution->close();
1818 system.update();
1819}
void read_global_variable(std::vector< std::string > global_var_names, unsigned int timestep, std::vector< Real > &global_values)
Given a vector of global variables and a time step, returns the values of the global variable at the ...
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

References libMesh::System::get_dof_map(), libMesh::index_range(), libMesh::ParallelObject::n_processors(), nemhelper, libMesh::ParallelObject::processor_id(), read_global_variable(), libMesh::DofMap::SCALAR_dof_indices(), libMesh::System::solution, libMesh::System::update(), and libMesh::System::variable_scalar_number().

◆ get_add_sides()

virtual bool libMesh::MeshOutput< MeshBase >::get_add_sides ( )
inlineprotectedvirtualinherited
Returns
Whether or not added sides are expected to be output, to plot SIDE_DISCONTINUOUS data. Subclasses should override this if they are capable of plotting such data.

Reimplemented in libMesh::ExodusII_IO.

Definition at line 176 of file mesh_output.h.

176{ return false; }

◆ get_elem_var_names()

const std::vector< std::string > & libMesh::Nemesis_IO::get_elem_var_names ( )

Return list of the elemental variable names.

Definition at line 1670 of file nemesis_io.C.

1671{
1673 return nemhelper->elem_var_names;
1674}

References libMesh::ExodusII_IO_Helper::ELEMENTAL, and nemhelper.

◆ get_global_var_names()

const std::vector< std::string > & libMesh::Nemesis_IO::get_global_var_names ( )

Return list of the global variable names.

Definition at line 1676 of file nemesis_io.C.

1677{
1678 nemhelper->read_var_names(ExodusII_IO_Helper::GLOBAL);
1679 return nemhelper->global_var_names;
1680}

References libMesh::ExodusII_IO_Helper::GLOBAL, and nemhelper.

◆ get_nemio_helper()

Nemesis_IO_Helper & libMesh::Nemesis_IO::get_nemio_helper ( )

Return a reference to the Nemesis_IO_Helper object.

Definition at line 1852 of file nemesis_io.C.

1853{
1854 // Provide a warning when accessing the helper object
1855 // since it is a non-public API and is likely to see
1856 // future API changes
1857 libmesh_experimental();
1858
1859 return *nemhelper;
1860}

References nemhelper.

◆ get_nodal_var_names()

const std::vector< std::string > & libMesh::Nemesis_IO::get_nodal_var_names ( )

Return list of the nodal variable names.

Definition at line 1664 of file nemesis_io.C.

1665{
1666 nemhelper->read_var_names(ExodusII_IO_Helper::NODAL);
1667 return nemhelper->nodal_var_names;
1668}

References nemhelper, and libMesh::ExodusII_IO_Helper::NODAL.

Referenced by WriteVecAndScalar::testWriteNemesis().

◆ get_num_time_steps()

int libMesh::Nemesis_IO::get_num_time_steps ( )
Returns
The number of timesteps currently stored in the Exodus file.

Knowing the number of time steps currently stored in the file is sometimes necessary when appending, so we can know where to start writing new data. Throws an error if the file is not currently open for reading or writing.

Definition at line 1694 of file nemesis_io.C.

1695{
1696 libmesh_error_msg_if(!nemhelper->opened_for_reading && !nemhelper->opened_for_writing,
1697 "ERROR, ExodusII file must be opened for reading or writing before calling Nemesis_IO::get_num_time_steps()!");
1698
1699 nemhelper->read_num_time_steps();
1700 return nemhelper->num_time_steps;
1701}

References nemhelper.

◆ get_time_steps()

const std::vector< Real > & libMesh::Nemesis_IO::get_time_steps ( )
Returns
An array containing the timesteps in the file.

Definition at line 1683 of file nemesis_io.C.

1684{
1685 libmesh_error_msg_if
1686 (!nemhelper->opened_for_reading,
1687 "ERROR, ExodusII file must be opened for reading before calling Nemesis_IO::get_time_steps()!");
1688
1689 nemhelper->read_time_steps();
1690 return nemhelper->time_steps;
1691}

References nemhelper.

◆ is_parallel_format()

bool libMesh::MeshInput< MeshBase >::is_parallel_format ( ) const
inlineinherited

Returns true iff this mesh file format and input class are parallelized, so that all processors can read their share of the data at once.

Definition at line 87 of file mesh_input.h.

87{ return this->_is_parallel_format; }
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
Definition mesh_input.h:130

◆ mesh() [1/2]

MeshBase & libMesh::MeshInput< MeshBase >::mesh ( )
inlineprotectedinherited
Returns
The object as a writable reference.

Definition at line 94 of file mesh_input.h.

179{
180 libmesh_error_msg_if(_obj == nullptr, "ERROR: _obj should not be nullptr!");
181 return *_obj;
182}
MeshBase * _obj
A pointer to a non-const object object.
Definition mesh_input.h:123

◆ mesh() [2/2]

const MeshBase & libMesh::MeshOutput< MeshBase >::mesh ( ) const
inlineprotectedinherited
Returns
The object as a read-only reference.

Definition at line 168 of file mesh_output.h.

260{
261 libmesh_assert(_obj);
262 return *_obj;
263}
const MeshBase *const _obj
A pointer to a constant object.

◆ 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
uint8_t processor_id_type
Definition id_types.h:104

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(), 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(), 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(), libMesh::ExodusII_IO_Helper::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(), 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(), libMesh::ExodusII_IO_Helper::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().

◆ prepare_to_write_nodal_data()

void libMesh::Nemesis_IO::prepare_to_write_nodal_data ( const std::string &  fname,
const std::vector< std::string > &  names 
)
private

Helper function containing code shared between the two different versions of write_nodal_data which take std::vector and NumericVector, respectively.

Definition at line 1318 of file nemesis_io.C.

1320{
1321 const MeshBase & mesh = MeshOutput<MeshBase>::mesh();
1322
1323 std::string nemesis_filename = nemhelper->construct_nemesis_filename(fname);
1324
1325 if (!nemhelper->opened_for_writing)
1326 {
1327 // If we're appending, open() the file with read_only=false,
1328 // otherwise create() it and write the contents of the mesh to
1329 // it.
1330 if (_append)
1331 {
1332 nemhelper->open(nemesis_filename.c_str(), /*read_only=*/false);
1333 // After opening the file, read the header so that certain
1334 // fields, such as the number of nodes and the number of
1335 // elements, are correctly initialized for the subsequent
1336 // call to write the nodal solution.
1337 nemhelper->read_and_store_header_info();
1338
1339 // ...and reading the block info
1340 nemhelper->read_block_info();
1341
1342 // ...and rebuild the "exodus_node_num_to_libmesh" map
1343 nemhelper->compute_num_global_elem_blocks(mesh);
1344 nemhelper->build_element_and_node_maps(mesh);
1345 }
1346 else
1347 {
1348 nemhelper->create(nemesis_filename);
1349 nemhelper->initialize(nemesis_filename,mesh);
1350
1351 // Make sure we're writing communication maps we can reuse
1352 // as expected when reading
1353 this->assert_symmetric_cmaps();
1354
1355 nemhelper->write_nodal_coordinates(mesh);
1356 nemhelper->write_elements(mesh);
1357 nemhelper->write_nodesets(mesh);
1358 nemhelper->write_sidesets(mesh);
1359
1361 libmesh_warning("Warning: Mesh contains edge boundary IDs, but these "
1362 "are not supported by the ExodusII format.");
1363 }
1364 }
1365
1366 // Even if we were already open for writing, we might not have
1367 // initialized the nodal variable names yet. Even if we did, it
1368 // should not hurt to call this twice because the routine sets a
1369 // flag the first time it is called.
1370#ifdef LIBMESH_USE_COMPLEX_NUMBERS
1371 std::vector<std::string> complex_names =
1372 nemhelper->get_complex_names(names, nemhelper->write_complex_abs);
1373 nemhelper->initialize_nodal_variables(complex_names);
1374#else
1375 nemhelper->initialize_nodal_variables(names);
1376#endif
1377}
std::size_t n_edge_conds() const
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
const MT & mesh() const
void assert_symmetric_cmaps()
Definition nemesis_io.C:178

References _append, _verbose, assert_symmetric_cmaps(), libMesh::MeshBase::get_boundary_info(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::mesh(), libMesh::BoundaryInfo::n_edge_conds(), and nemhelper.

Referenced by write_nodal_data(), write_nodal_data(), and write_nodal_data().

◆ 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(), 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(), libMesh::ExodusII_IO_Helper::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(), copy_scalar_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::ExodusII_IO_Helper::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(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize_element_variables(), libMesh::ExodusII_IO_Helper::initialize_global_variables(), libMesh::ExodusII_IO_Helper::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(), read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::EquationSystems::read(), libMesh::EquationSystems::read(), libMesh::ExodusII_IO_Helper::read_elem_num_map(), libMesh::ExodusII_IO_Helper::read_global_values(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::DynaIO::read_mesh(), libMesh::ExodusII_IO_Helper::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(), libMesh::ExodusII_IO_Helper::write_element_values(), libMesh::ExodusII_IO_Helper::write_element_values_element_major(), libMesh::ExodusII_IO_Helper::write_elements(), libMesh::ExodusII_IO_Helper::write_elemset_data(), libMesh::ExodusII_IO_Helper::write_elemsets(), libMesh::ExodusII_IO::write_global_data(), libMesh::ExodusII_IO_Helper::write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), libMesh::ExodusII_IO_Helper::write_information_records(), libMesh::ExodusII_IO_Helper::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(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::ExodusII_IO_Helper::write_nodeset_data(), libMesh::ExodusII_IO_Helper::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(), libMesh::ExodusII_IO_Helper::write_sideset_data(), libMesh::ExodusII_IO_Helper::write_sidesets(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), libMesh::ExodusII_IO_Helper::write_timestep(), and libMesh::ExodusII_IO::write_timestep_discontinuous().

◆ read()

void libMesh::Nemesis_IO::read ( const std::string &  base_filename)
overridevirtual

Implements reading the mesh from several different files.

You provide the basename, then LibMesh appends the ".size.rank" depending on this->n_processors() and this->processor_id().

Implements libMesh::MeshInput< MeshBase >.

Definition at line 215 of file nemesis_io.C.

216{
217 LOG_SCOPE ("read()","Nemesis_IO");
218
219 // This function must be run on all processors at once
220 parallel_object_only();
221
222 if (_verbose)
223 {
224 libMesh::out << "[" << this->processor_id() << "] ";
225 libMesh::out << "Reading Nemesis file on processor: " << this->processor_id() << std::endl;
226 }
227
228 // Construct the Nemesis filename based on the number of processors and the
229 // current processor ID.
230 std::string nemesis_filename = nemhelper->construct_nemesis_filename(base_filename);
231
232 if (_verbose)
233 libMesh::out << "Opening file: " << nemesis_filename << std::endl;
234
235 // Open the Exodus file in EX_READ mode
236 nemhelper->open(nemesis_filename.c_str(), /*read_only=*/true);
237
238 // Get a reference to the mesh. We need to be specific
239 // since Nemesis_IO is multiply-inherited
240 // MeshBase & mesh = this->mesh();
241 MeshBase & mesh = MeshInput<MeshBase>::mesh();
242
243 // We're reading a file on each processor, so our mesh is
244 // partitioned into that many parts as it's created
245 this->set_n_partitions(this->n_processors());
246
247 // Local information: Read the following information from the standard Exodus header
248 // title[0]
249 // num_dim
250 // num_nodes
251 // num_elem
252 // num_elem_blk
253 // num_node_sets
254 // num_side_sets
255 nemhelper->read_and_store_header_info();
256 nemhelper->print_header();
257
258 // Get global information: number of nodes, elems, blocks, nodesets and sidesets
259 nemhelper->get_init_global();
260
261 // Get "load balance" information. This includes the number of internal & border
262 // nodes and elements as well as the number of communication maps.
263 nemhelper->get_loadbal_param();
264
265 // Do some error checking
266 libmesh_error_msg_if(nemhelper->num_external_nodes,
267 "ERROR: there should be no external nodes in an element-based partitioning!");
268
269 libmesh_assert_equal_to (nemhelper->num_nodes,
270 (nemhelper->num_internal_nodes +
271 nemhelper->num_border_nodes));
272
273 libmesh_assert_equal_to (nemhelper->num_elem,
274 (nemhelper->num_internal_elems +
275 nemhelper->num_border_elems));
276
277 libmesh_assert_less_equal (nemhelper->num_nodes, nemhelper->num_nodes_global);
278 libmesh_assert_less_equal (nemhelper->num_elem, nemhelper->num_elems_global);
279
280 // Read nodes from the exodus file: this fills the nemhelper->x,y,z arrays.
281 nemhelper->read_nodes();
282
283 // Reads the nemhelper->node_num_map array, node_num_map[i] is the global node number for
284 // local node number i.
285 nemhelper->read_node_num_map();
286
287 // The get_cmap_params() function reads in the:
288 // node_cmap_ids[],
289 // node_cmap_node_cnts[],
290 // elem_cmap_ids[],
291 // elem_cmap_elem_cnts[],
292 nemhelper->get_cmap_params();
293
294 // Read the IDs of the interior, boundary, and external nodes. This function
295 // fills the vectors:
296 // node_mapi[],
297 // node_mapb[],
298 // node_mape[]
299 nemhelper->get_node_map();
300
301 // Read each node communication map for this processor. This function
302 // fills the vectors of vectors named:
303 // node_cmap_node_ids[][]
304 // node_cmap_proc_ids[][]
305 nemhelper->get_node_cmap();
306
307 libmesh_assert_equal_to (to_uint(nemhelper->num_node_cmaps), nemhelper->node_cmap_node_cnts.size());
308 libmesh_assert_equal_to (to_uint(nemhelper->num_node_cmaps), nemhelper->node_cmap_node_ids.size());
309 libmesh_assert_equal_to (to_uint(nemhelper->num_node_cmaps), nemhelper->node_cmap_proc_ids.size());
310
312
313 // We now have enough information to infer node ownership. We start by assuming
314 // we own all the nodes on this processor. We will then interrogate the
315 // node cmaps and see if a lower-rank processor is associated with any of
316 // our nodes. If so, then that processor owns the node, not us...
317 std::vector<processor_id_type> node_ownership (nemhelper->num_internal_nodes +
318 nemhelper->num_border_nodes,
319 this->processor_id());
320
321 // a map from processor id to cmap number, to be used later
322 std::map<unsigned int, unsigned int> pid_to_cmap_map;
323
324 // For each node_cmap...
325 for (unsigned int cmap=0; cmap<to_uint(nemhelper->num_node_cmaps); cmap++)
326 {
327 // Good time for error checking...
328 libmesh_assert_equal_to (to_uint(nemhelper->node_cmap_node_cnts[cmap]),
329 nemhelper->node_cmap_node_ids[cmap].size());
330
331 libmesh_assert_equal_to (to_uint(nemhelper->node_cmap_node_cnts[cmap]),
332 nemhelper->node_cmap_proc_ids[cmap].size());
333
334 // In all the samples I have seen, node_cmap_ids[cmap] is the processor
335 // rank of the remote processor...
336 const processor_id_type adjcnt_pid_idx =
337 cast_int<processor_id_type>(nemhelper->node_cmap_ids[cmap]);
338
339 libmesh_assert_less (adjcnt_pid_idx, this->n_processors());
340 libmesh_assert_not_equal_to (adjcnt_pid_idx, this->processor_id());
341
342 // We only expect one cmap per adjacent processor
343 libmesh_assert (!pid_to_cmap_map.count(adjcnt_pid_idx));
344
345 pid_to_cmap_map[adjcnt_pid_idx] = cmap;
346
347 // ...and each node in that cmap...
348 for (unsigned int idx=0; idx<to_uint(nemhelper->node_cmap_node_cnts[cmap]); idx++)
349 {
350 // Are the node_cmap_ids and node_cmap_proc_ids really redundant?
351 libmesh_assert_equal_to
352 (adjcnt_pid_idx,
353 cast_int<processor_id_type>(nemhelper->node_cmap_proc_ids[cmap][idx]));
354
355 // we are expecting the exodus node numbering to be 1-based...
356 const unsigned int local_node_idx = nemhelper->node_cmap_node_ids[cmap][idx]-1;
357
358 libmesh_assert_less (local_node_idx, node_ownership.size());
359
360 // if the adjacent processor is lower rank than the current
361 // owner for this node, then it will get the node...
362 node_ownership[local_node_idx] =
363 std::min(node_ownership[local_node_idx], adjcnt_pid_idx);
364 }
365 } // We now should have established proper node ownership.
366
367 // now that ownership is established, we can figure out how many nodes we
368 // will be responsible for numbering.
369 unsigned int num_nodes_i_must_number = 0;
370
371 for (const auto & pid : node_ownership)
372 if (pid == this->processor_id())
373 num_nodes_i_must_number++;
374
375 // more error checking...
376 libmesh_assert_greater_equal (num_nodes_i_must_number, nemhelper->num_internal_nodes);
377 libmesh_assert (num_nodes_i_must_number <= to_uint(nemhelper->num_internal_nodes +
378 nemhelper->num_border_nodes));
379 if (_verbose)
380 libMesh::out << "[" << this->processor_id() << "] "
381 << "num_nodes_i_must_number="
382 << num_nodes_i_must_number
383 << std::endl;
384
385 // The call to get_loadbal_param() gets 7 pieces of information. We allgather
386 // these now across all processors to determine some global numberings. We should
387 // also gather the number of nodes each processor thinks it will number so that
388 // we can (i) determine our offset, and (ii) do some error checking.
389 std::vector<int> all_loadbal_data ( 8 );
390 all_loadbal_data[0] = nemhelper->num_internal_nodes;
391 all_loadbal_data[1] = nemhelper->num_border_nodes;
392 all_loadbal_data[2] = nemhelper->num_external_nodes;
393 all_loadbal_data[3] = nemhelper->num_internal_elems;
394 all_loadbal_data[4] = nemhelper->num_border_elems;
395 all_loadbal_data[5] = nemhelper->num_node_cmaps;
396 all_loadbal_data[6] = nemhelper->num_elem_cmaps;
397 all_loadbal_data[7] = num_nodes_i_must_number;
398
399 this->comm().allgather (all_loadbal_data, /* identical_buffer_sizes = */ true);
400
401 // OK, we are now in a position to request new global indices for all the nodes
402 // we do not own
403
404 // Let's get a unique message tag to use for send()/receive()
405 Parallel::MessageTag nodes_tag = mesh.comm().get_unique_tag();
406
407 std::vector<std::vector<int>>
408 needed_node_idxs (nemhelper->num_node_cmaps); // the indices we will ask for
409
410 std::vector<Parallel::Request>
411 needed_nodes_requests (nemhelper->num_node_cmaps);
412
413 for (unsigned int cmap=0; cmap<to_uint(nemhelper->num_node_cmaps); cmap++)
414 {
415 // We know we will need no more indices than there are nodes
416 // in this cmap, but that number is an upper bound in general
417 // since the neighboring processor associated with the cmap
418 // may not actually own it
419 needed_node_idxs[cmap].reserve (nemhelper->node_cmap_node_cnts[cmap]);
420
421 const unsigned int adjcnt_pid_idx = nemhelper->node_cmap_ids[cmap];
422
423 // ...and each node in that cmap...
424 for (unsigned int idx=0; idx<to_uint(nemhelper->node_cmap_node_cnts[cmap]); idx++)
425 {
426 const unsigned int
427 local_node_idx = nemhelper->node_cmap_node_ids[cmap][idx]-1,
428 owning_pid_idx = node_ownership[local_node_idx];
429
430 // add it to the request list for its owning processor.
431 if (owning_pid_idx == adjcnt_pid_idx)
432 {
433 const unsigned int
434 global_node_idx = nemhelper->node_num_map[local_node_idx]-1;
435 needed_node_idxs[cmap].push_back(global_node_idx);
436 }
437 }
438 // now post the send for this cmap
439 this->comm().send (adjcnt_pid_idx, // destination
440 needed_node_idxs[cmap], // send buffer
441 needed_nodes_requests[cmap], // request
442 nodes_tag);
443 } // all communication requests for getting updated global indices for border
444 // nodes have been initiated
445
446 // Figure out how many nodes each processor thinks it will number and make sure
447 // that it adds up to the global number of nodes. Also, set up global node
448 // index offsets for each processor.
449 std::vector<unsigned int>
450 all_num_nodes_i_must_number (this->n_processors());
451
452 for (auto pid : make_range(this->n_processors()))
453 all_num_nodes_i_must_number[pid] = all_loadbal_data[8*pid + 7];
454
455 // The sum of all the entries in this vector should sum to the number of global nodes
456 libmesh_assert (std::accumulate(all_num_nodes_i_must_number.begin(),
457 all_num_nodes_i_must_number.end(),
458 0) == nemhelper->num_nodes_global);
459
460 unsigned int my_next_node = 0;
461 for (auto pid : make_range(this->processor_id()))
462 my_next_node += all_num_nodes_i_must_number[pid];
463
464 const unsigned int my_node_offset = my_next_node;
465
466 if (_verbose)
467 libMesh::out << "[" << this->processor_id() << "] "
468 << "my_node_offset="
469 << my_node_offset
470 << std::endl;
471
472 // Add internal nodes to the DistributedMesh, using the node ID offset we
473 // computed and the current processor's ID.
474 for (unsigned int i=0; i<to_uint(nemhelper->num_internal_nodes); ++i)
475 {
476 const unsigned int local_node_idx = nemhelper->node_mapi[i]-1;
477#ifndef NDEBUG
478 const unsigned int owning_pid_idx = node_ownership[local_node_idx];
479#endif
480
481 // an internal node we do not own? huh??
482 libmesh_assert_equal_to (owning_pid_idx, this->processor_id());
483 libmesh_assert_less (my_next_node, nemhelper->num_nodes_global);
484
485 // "Catch" the node pointer after addition, make sure the
486 // ID matches the requested value.
487 Node * added_node =
488 mesh.add_point (Point(nemhelper->x[local_node_idx],
489 nemhelper->y[local_node_idx],
490 nemhelper->z[local_node_idx]),
491 my_next_node,
492 this->processor_id());
493
494 // Make sure the node we added has the ID we thought it would
495 if (added_node->id() != my_next_node)
496 {
497 libMesh::err << "Error, node added with ID " << added_node->id()
498 << ", but we wanted ID " << my_next_node << std::endl;
499 }
500
501 // Set a unique_id ourselves since ReplicatedMesh can't handle
502 // distributed unique_id generation. Make sure it doesn't
503 // overlap element unique_id() values either.
504#ifdef LIBMESH_ENABLE_UNIQUE_ID
505 added_node->set_unique_id(added_node->id() + nemhelper->num_elems_global);
506#endif
507
508 // update the local->global index map, keeping it 1-based
509 nemhelper->node_num_map[local_node_idx] = my_next_node++ + 1;
510 }
511
512 // Now, for the boundary nodes... We may very well own some of them,
513 // but there may be others for which we have requested the new global
514 // id. We expect to be asked for the ids of the ones we own, so
515 // we need to create a map from the old global id to the new one
516 // we are about to create.
517 typedef std::vector<std::pair<unsigned int, unsigned int>> global_idx_mapping_type;
518 global_idx_mapping_type old_global_to_new_global_map;
519 old_global_to_new_global_map.reserve (num_nodes_i_must_number // total # i will have
520 - (my_next_node // amount i have thus far
521 - my_node_offset)); // this should be exact!
522 CompareGlobalIdxMappings global_idx_mapping_comp;
523
524 for (unsigned int i=0; i<to_uint(nemhelper->num_border_nodes); ++i)
525 {
526 const unsigned int
527 local_node_idx = nemhelper->node_mapb[i]-1,
528 owning_pid_idx = node_ownership[local_node_idx];
529
530 // if we own it...
531 if (owning_pid_idx == this->processor_id())
532 {
533 const unsigned int
534 global_node_idx = nemhelper->node_num_map[local_node_idx]-1;
535
536 // we will number it, and create a mapping from its old global index to
537 // the new global index, for lookup purposes when neighbors come calling
538 old_global_to_new_global_map.emplace_back(global_node_idx, my_next_node);
539
540 // "Catch" the node pointer after addition, make sure the
541 // ID matches the requested value.
542 Node * added_node =
543 mesh.add_point (Point(nemhelper->x[local_node_idx],
544 nemhelper->y[local_node_idx],
545 nemhelper->z[local_node_idx]),
546 my_next_node,
547 this->processor_id());
548
549 // Make sure the node we added has the ID we thought it would
550 if (added_node->id() != my_next_node)
551 {
552 libMesh::err << "Error, node added with ID " << added_node->id()
553 << ", but we wanted ID " << my_next_node << std::endl;
554 }
555
556 // Set a unique_id ourselves since ReplicatedMesh can't handle
557 // distributed unique_id generation. Make sure it doesn't
558 // overlap element unique_id() values either.
559#ifdef LIBMESH_ENABLE_UNIQUE_ID
560 added_node->set_unique_id(added_node->id() + nemhelper->num_elems_global);
561#endif
562
563 // update the local->global index map, keeping it 1-based
564 nemhelper->node_num_map[local_node_idx] = my_next_node++ + 1;
565 }
566 }
567 // That should cover numbering all the nodes which belong to us...
568 libmesh_assert_equal_to (num_nodes_i_must_number, (my_next_node - my_node_offset));
569
570 // Let's sort the mapping so we can efficiently answer requests
571 std::sort (old_global_to_new_global_map.begin(),
572 old_global_to_new_global_map.end(),
573 global_idx_mapping_comp);
574
575 // and it had better be unique...
576 libmesh_assert (std::unique (old_global_to_new_global_map.begin(),
577 old_global_to_new_global_map.end(),
578 global_idx_mapping_equality) ==
579 old_global_to_new_global_map.end());
580
581 // We can now catch incoming requests and process them. for efficiency
582 // let's do whatever is available next
583 std::map<unsigned int, std::vector<int>> requested_node_idxs; // the indices asked of us
584
585 std::vector<Parallel::Request> requested_nodes_requests(nemhelper->num_node_cmaps);
586
587 // We know we will receive the request from a given processor before
588 // we receive its reply to our request. However, we may receive
589 // a request and a response from one processor before getting
590 // a request from another processor. So what we are doing here
591 // is processing whatever message comes next, while recognizing
592 // we will receive a request from a processor before receiving
593 // its reply
594 std::vector<bool> processed_cmap (nemhelper->num_node_cmaps, false);
595
596 for (unsigned int comm_step=0; comm_step<2*to_uint(nemhelper->num_node_cmaps); comm_step++)
597 {
598 // query the first message which is available
599 const Parallel::Status
600 status (this->comm().probe (Parallel::any_source,
601 nodes_tag));
602 const unsigned int
603 requesting_pid_idx = status.source(),
604 source_pid_idx = status.source();
605
606 // this had better be from a processor we are expecting...
607 libmesh_assert (pid_to_cmap_map.count(requesting_pid_idx));
608
609 // the local cmap which corresponds to the source processor
610 const unsigned int cmap = pid_to_cmap_map[source_pid_idx];
611
612 if (!processed_cmap[cmap])
613 {
614 processed_cmap[cmap] = true;
615
616 // we should only get one request per paired processor
617 libmesh_assert (!requested_node_idxs.count(requesting_pid_idx));
618
619 // get a reference to the request buffer for this processor to
620 // avoid repeated map lookups
621 std::vector<int> & xfer_buf (requested_node_idxs[requesting_pid_idx]);
622
623 // actually receive the message.
624 this->comm().receive (requesting_pid_idx, xfer_buf, nodes_tag);
625
626 // Fill the request
627 for (auto i : index_range(xfer_buf))
628 {
629 // the requested old global node index, *now 0-based*
630 const unsigned int old_global_node_idx = xfer_buf[i];
631
632 // find the new global node index for the requested node -
633 // note that requesting_pid_idx thinks we own this node,
634 // so we better!
635 const global_idx_mapping_type::const_iterator it =
636 std::lower_bound (old_global_to_new_global_map.begin(),
637 old_global_to_new_global_map.end(),
638 old_global_node_idx,
639 global_idx_mapping_comp);
640
641 libmesh_assert (it != old_global_to_new_global_map.end());
642 libmesh_assert_equal_to (it->first, old_global_node_idx);
643 libmesh_assert_greater_equal (it->second, my_node_offset);
644 libmesh_assert_less (it->second, my_next_node);
645
646 // overwrite the requested old global node index with the new global index
647 xfer_buf[i] = it->second;
648 }
649
650 // and send the new global indices back to the processor which asked for them
651 this->comm().send (requesting_pid_idx,
652 xfer_buf,
653 requested_nodes_requests[cmap],
654 nodes_tag);
655 } // done processing the request
656
657 // this is the second time we have heard from this processor,
658 // so it must be its reply to our request
659 else
660 {
661 // a long time ago, we sent off our own requests. now it is time to catch the
662 // replies and get the new global node numbering. note that for any reply
663 // we receive, the corresponding nonblocking send from above *must* have been
664 // completed, since the reply is in response to that request!!
665
666 // if we have received a reply, our send *must* have completed
667 // (note we never actually need to wait on the request)
668 libmesh_assert (needed_nodes_requests[cmap].test());
669 libmesh_assert_equal_to (to_uint(nemhelper->node_cmap_ids[cmap]), source_pid_idx);
670
671 // now post the receive for this cmap
672 this->comm().receive (source_pid_idx,
673 needed_node_idxs[cmap],
674 nodes_tag);
675
676 libmesh_assert_less_equal (needed_node_idxs[cmap].size(),
677 nemhelper->node_cmap_node_ids[cmap].size());
678
679 for (std::size_t i=0, j=0, ncnis=nemhelper->node_cmap_node_ids[cmap].size(); i < ncnis; i++)
680 {
681 const unsigned int
682 local_node_idx = nemhelper->node_cmap_node_ids[cmap][i]-1,
683 owning_pid_idx = node_ownership[local_node_idx];
684
685 // if this node is owned by source_pid_idx, its new global id
686 // is in the buffer we just received
687 if (owning_pid_idx == source_pid_idx)
688 {
689 libmesh_assert_less (j, needed_node_idxs[cmap].size());
690
691 const unsigned int // now 0-based!
692 global_node_idx = needed_node_idxs[cmap][j++];
693
694 // "Catch" the node pointer after addition, make sure the
695 // ID matches the requested value.
696 Node * added_node =
697 mesh.add_point (Point(nemhelper->x[local_node_idx],
698 nemhelper->y[local_node_idx],
699 nemhelper->z[local_node_idx]),
700 cast_int<dof_id_type>(global_node_idx),
701 cast_int<processor_id_type>(source_pid_idx));
702
703 // Make sure the node we added has the ID we thought it would
704 if (added_node->id() != global_node_idx)
705 {
706 libMesh::err << "Error, node added with ID " << added_node->id()
707 << ", but we wanted ID " << global_node_idx << std::endl;
708 }
709
710 // Set a unique_id ourselves since ReplicatedMesh can't handle
711 // distributed unique_id generation. Make sure it doesn't
712 // overlap element unique_id() values either.
713#ifdef LIBMESH_ENABLE_UNIQUE_ID
714 added_node->set_unique_id(added_node->id() + nemhelper->num_elems_global);
715#endif
716
717 // update the local->global index map, keeping it 1-based
718 nemhelper->node_num_map[local_node_idx] = global_node_idx + 1;
719
720 // we are not really going to use my_next_node again, but we can
721 // keep incrementing it to track how many nodes we have added
722 // to the mesh
723 my_next_node++;
724 }
725 }
726 }
727 } // end of node index communication loop
728
729 // we had better have added all the nodes we need to!
730 libmesh_assert_equal_to ((my_next_node - my_node_offset), to_uint(nemhelper->num_nodes));
731
732 // After all that, we should be done with all node-related arrays
733 // *except* the node_num_map.
734 // So let's clean up the arrays we are done with.
735 {
736 Utility::deallocate (nemhelper->node_mapi);
737 Utility::deallocate (nemhelper->node_mapb);
738 Utility::deallocate (nemhelper->node_mape);
739 Utility::deallocate (nemhelper->node_cmap_ids);
740 Utility::deallocate (nemhelper->node_cmap_node_cnts);
741 Utility::deallocate (nemhelper->node_cmap_node_ids);
742 Utility::deallocate (nemhelper->node_cmap_proc_ids);
746 Utility::deallocate (needed_node_idxs);
747 Utility::deallocate (node_ownership);
748 }
749
750 Parallel::wait (needed_nodes_requests);
751 Parallel::wait (requested_nodes_requests);
752 requested_node_idxs.clear();
753
754 // See what the node count is up to now.
755 if (_verbose)
756 {
757 // Report the number of nodes which have been added locally
758 libMesh::out << "[" << this->processor_id() << "] ";
759 libMesh::out << "mesh.n_nodes()=" << mesh.n_nodes() << std::endl;
760
761 // Reports the number of nodes that have been added in total.
762 libMesh::out << "[" << this->processor_id() << "] ";
763 libMesh::out << "mesh.parallel_n_nodes()=" << mesh.parallel_n_nodes() << std::endl;
764 }
765
766
767
768 // --------------------------------------------------------------------------------
769 // --------------------------------------------------------------------------------
770 // --------------------------------------------------------------------------------
771
772
773 // We can now read in the elements...Exodus stores them in blocks in which all
774 // elements have the same geometric type. This code is adapted directly from exodusII_io.C
775
776 // Assertion: The sum of the border and internal elements on all processors
777 // should equal nemhelper->num_elems_global
778#ifndef NDEBUG
779 {
780 int sum_internal_elems=0, sum_border_elems=0;
781 for (unsigned int j=3,c=0; c<this->n_processors(); j+=8,++c)
782 sum_internal_elems += all_loadbal_data[j];
783
784 for (unsigned int j=4,c=0; c<this->n_processors(); j+=8,++c)
785 sum_border_elems += all_loadbal_data[j];
786
787 if (_verbose)
788 {
789 libMesh::out << "[" << this->processor_id() << "] ";
790 libMesh::out << "sum_internal_elems=" << sum_internal_elems << std::endl;
791
792 libMesh::out << "[" << this->processor_id() << "] ";
793 libMesh::out << "sum_border_elems=" << sum_border_elems << std::endl;
794 }
795
796 libmesh_assert_equal_to (sum_internal_elems+sum_border_elems, nemhelper->num_elems_global);
797 }
798#endif
799
800 // We need to set the mesh dimension, but the following...
801 // mesh.set_mesh_dimension(static_cast<unsigned int>(nemhelper->num_dim));
802
803 // ... is not sufficient since some codes report num_dim==3 for two dimensional
804 // meshes living in 3D, even though all the elements are of 2D type. Therefore,
805 // we instead use the dimension of the highest element found for the Mesh dimension,
806 // similar to what is done by the Exodus reader, except here it requires a
807 // parallel communication.
808 elems_of_dimension.resize(4, false); // will use 1-based
809
810 // Fills in the:
811 // global_elem_blk_ids[] and
812 // global_elem_blk_cnts[] arrays.
813 nemhelper->get_eb_info_global();
814
815 // // Fills in the vectors
816 // // elem_mapi[num_internal_elems]
817 // // elem_mapb[num_border_elems ]
818 // // These tell which of the (locally-numbered) elements are internal and which are border elements.
819 // // In our test example these arrays are sorted (but non-contiguous), which makes it possible to
820 // // binary search for each element ID... however I don't think we need to distinguish between the
821 // // two types, since either can have nodes the boundary!
822 // nemhelper->get_elem_map();
823
824 // Fills in the vectors of vectors:
825 // elem_cmap_elem_ids[][]
826 // elem_cmap_side_ids[][]
827 // elem_cmap_proc_ids[][]
828 // These arrays are of size num_elem_cmaps * elem_cmap_elem_cnts[i], i = 0..num_elem_cmaps
829 nemhelper->get_elem_cmap();
830
831 // Get information about the element blocks:
832 // (read in the array nemhelper->block_ids[])
833 nemhelper->read_block_info();
834
835 // Reads the nemhelper->elem_num_map array.
836 // elem_num_map[i] is the exodus element number for local element
837 // number i, which makes elem_num_map[i]-1 the libMesh element
838 // number.
839 nemhelper->read_elem_num_map();
840
841 std::size_t local_elem_num = 0;
842
843 // Read in the element connectivity for each block by
844 // looping over all the blocks.
845 for (unsigned int i=0; i<to_uint(nemhelper->num_elem_blk); i++)
846 {
847 // Read the information for block i: For nemhelper->block_ids[i], reads
848 // elem_type
849 // num_elem_this_blk
850 // num_nodes_per_elem
851 // num_attr
852 // connect <-- the nodal connectivity array for each element in the block.
853 nemhelper->read_elem_in_block(i);
854
855 // Note that with parallel files it is possible we have no elements in
856 // this block!
857 if (!nemhelper->num_elem_this_blk) continue;
858
859 // Set subdomain ID based on the block ID.
860 subdomain_id_type subdomain_id =
861 restrict_int<subdomain_id_type>(nemhelper->block_ids[i]);
862
863 // Create a type string (this uses the null-terminated string ctor).
864 const std::string type_str ( nemhelper->elem_type.data() );
865
866 // Set any relevant node/edge maps for this element
867 const auto & conv = nemhelper->get_conversion(type_str);
868
869 if (_verbose)
870 libMesh::out << "Reading a block of " << type_str << " elements." << std::endl;
871
872 // Loop over all the elements in this block
873 for (unsigned int j=0; j<to_uint(nemhelper->num_elem_this_blk); j++)
874 {
875 auto uelem = Elem::build (conv.libmesh_elem_type());
876
877 // Assign subdomain and processor ID to the newly-created Elem.
878 // Assigning the processor ID beforehand ensures that the Elem is
879 // not added as an "unpartitioned" element. Note that the element
880 // numbering in Exodus is also 1-based.
881 uelem->subdomain_id() = subdomain_id;
882 uelem->processor_id() = this->processor_id();
883 uelem->set_id() = nemhelper->elem_num_map[local_elem_num++]-1;
884
885 // Handle unique_id numbering, just in case we're using a
886 // ReplicatedMesh that doesn't know how to handle it in
887 // parallel.
888#ifdef LIBMESH_ENABLE_UNIQUE_ID
889 uelem->set_unique_id(uelem->id());
890#endif
891
892 // Mark that we have seen an element of the current element's
893 // dimension.
894 elems_of_dimension[uelem->dim()] = true;
895
896 // Add the created Elem to the Mesh, catch the Elem
897 // pointer that the Mesh throws back.
898 Elem * elem = mesh.add_elem(std::move(uelem));
899
900 // We are expecting the element "thrown back" by libmesh to have the ID we specified for it...
901 // Check to see that really is the case. Note that local_elem_num was post-incremented, so
902 // subtract 1 when performing the check.
903 libmesh_assert_equal_to(elem->id(),
904 cast_int<dof_id_type>(nemhelper->elem_num_map[local_elem_num-1]-1));
905
906 // Set all the nodes for this element
907 if (_verbose)
908 libMesh::out << "[" << this->processor_id() << "] "
909 << "Setting nodes for Elem " << elem->id() << std::endl;
910
911 for (unsigned int k=0; k<to_uint(nemhelper->num_nodes_per_elem); k++)
912 {
913 const unsigned int
914 gi = (j*nemhelper->num_nodes_per_elem + // index into connectivity array
915 conv.get_node_map(k)),
916 local_node_idx = nemhelper->connect[gi]-1, // local node index
917 global_node_idx = nemhelper->node_num_map[local_node_idx]-1; // new global node index
918
919 // Set node number
920 elem->set_node(k, mesh.node_ptr(global_node_idx));
921 }
922 } // for (unsigned int j=0; j<nemhelper->num_elem_this_blk; j++)
923 } // end for (unsigned int i=0; i<nemhelper->num_elem_blk; i++)
924
925 for (const auto & [id, name] : nemhelper->id_to_block_names)
926 if (name != "")
927 mesh.set_subdomain_name(id, name);
928
929 if (_verbose)
930 {
931 // Print local elems_of_dimension information
932 for (auto i : IntRange<std::size_t>(1, elems_of_dimension.size()))
933 libMesh::out << "[" << this->processor_id() << "] "
934 << "elems_of_dimension[" << i << "]=" << elems_of_dimension[i] << std::endl;
935 }
936
937 // Get the max dimension seen on the current processor
938 unsigned char max_dim_seen = 0;
939 for (auto i : IntRange<std::size_t>(1, elems_of_dimension.size()))
941 max_dim_seen = static_cast<unsigned char>(i);
942
943 // Do a global max to determine the max dimension seen by all processors.
944 // It should match -- I don't think we even support calculations on meshes
945 // with elements of different dimension...
946 this->comm().max(max_dim_seen);
947
948 if (_verbose)
949 {
950 // Print the max element dimension from all processors
951 libMesh::out << "[" << this->processor_id() << "] "
952 << "max_dim_seen=" << +max_dim_seen << std::endl;
953 }
954
955 // Set the mesh dimension to the largest encountered for an element
956 mesh.set_mesh_dimension(max_dim_seen);
957
958#if LIBMESH_DIM < 3
959 libmesh_error_msg_if(mesh.mesh_dimension() > LIBMESH_DIM,
960 "Cannot open dimension "
962 << " mesh file when configured without "
964 << "D support." );
965#endif
966
967
968 // Global sideset information, they are distributed as well, not sure if they will require communication...?
969 nemhelper->get_ss_param_global();
970
971 if (_verbose)
972 {
973 libMesh::out << "[" << this->processor_id() << "] "
974 << "Read global sideset parameter information." << std::endl;
975
976 // These global values should be the same on all processors...
977 libMesh::out << "[" << this->processor_id() << "] "
978 << "Number of global sideset IDs: " << nemhelper->global_sideset_ids.size() << std::endl;
979 }
980
981 // Read *local* sideset info the same way it is done in
982 // exodusII_io_helper. May be called any time after
983 // nemhelper->read_and_store_header_info(); This sets num_side_sets and resizes
984 // elem_list, side_list, and id_list to num_elem_all_sidesets. Note
985 // that there appears to be the same number of sidesets in each file
986 // but they all have different numbers of entries (some are empty).
987 // Note that the sum of "nemhelper->num_elem_all_sidesets" over all
988 // processors should equal the sum of the entries in the "num_global_side_counts" array
989 // filled up by nemhelper->get_ss_param_global()
990 nemhelper->read_sideset_info();
991
992 if (_verbose)
993 {
994 libMesh::out << "[" << this->processor_id() << "] "
995 << "nemhelper->num_side_sets = " << nemhelper->num_side_sets << std::endl;
996
997 libMesh::out << "[" << this->processor_id() << "] "
998 << "nemhelper->num_elem_all_sidesets = " << nemhelper->num_elem_all_sidesets << std::endl;
999
1000 if (nemhelper->num_side_sets > 0)
1001 {
1002 libMesh::out << "Sideset names are: ";
1003 for (const auto & [id, name] : nemhelper->id_to_ss_names)
1004 libMesh::out << "(" << id << "," << name << ") ";
1005 libMesh::out << std::endl;
1006 }
1007 }
1008
1009#ifdef DEBUG
1010 {
1011 // In DEBUG mode, check that the global number of sidesets reported
1012 // in each nemesis file matches the sum of all local sideset counts
1013 // from each processor. This requires a small communication, so only
1014 // do it in DEBUG mode.
1015 int sum_num_global_side_counts = std::accumulate(nemhelper->num_global_side_counts.begin(),
1016 nemhelper->num_global_side_counts.end(),
1017 0);
1018
1019 // MPI sum up the local files contributions
1020 int sum_num_elem_all_sidesets = nemhelper->num_elem_all_sidesets;
1021 this->comm().sum(sum_num_elem_all_sidesets);
1022
1023 libmesh_error_msg_if(sum_num_global_side_counts != sum_num_elem_all_sidesets,
1024 "Error! global side count reported by Nemesis does not "
1025 "match the side count reported by the individual files!");
1026 }
1027#endif
1028
1029 // Note that exodus stores sidesets in separate vectors but we want to pack
1030 // them all into a single vector. So when we call read_sideset(), we pass an offset
1031 // into the single vector of all IDs
1032 for (int offset=0, i=0; i<nemhelper->num_side_sets; i++)
1033 {
1034 offset += (i > 0 ? nemhelper->num_sides_per_set[i-1] : 0); // Compute new offset
1035 nemhelper->read_sideset (i, offset);
1036 }
1037
1038 // Now that we have the lists of elements, sides, and IDs, we are ready to set them
1039 // in the BoundaryInfo object of our Mesh object. This is slightly different in parallel...
1040 // For example, I think the IDs in each of the split Exodus files are numbered locally,
1041 // and we have to know the appropriate ID for this processor to be able to set the
1042 // entry in BoundaryInfo. This id should be given by
1043 // elem_num_map[i]-1 for the local index i
1044
1045 // Debugging:
1046 // Print entries of elem_list
1047 // libMesh::out << "[" << this->processor_id() << "] "
1048 // << "elem_list = ";
1049 // for (const auto & id : nemhelper->elem_list)
1050 // libMesh::out << id << ", ";
1051 // libMesh::out << std::endl;
1052
1053 // Print entries of side_list
1054 // libMesh::out << "[" << this->processor_id() << "] "
1055 // << "side_list = ";
1056 // for (const auto & id : nemhelper->side_list)
1057 // libMesh::out << id << ", ";
1058 // libMesh::out << std::endl;
1059
1060
1061 // Loop over the entries of the elem_list, get their pointers from the
1062 // Mesh data structure, and assign the appropriate side to the BoundaryInfo object.
1063 for (auto e : index_range(nemhelper->elem_list))
1064 {
1065 // Exodus numbering is 1-based
1066 const std::size_t local_id = nemhelper->elem_list[e]-1;
1067 const dof_id_type elem_id = nemhelper->elem_num_map[local_id]-1;
1068
1069 Elem * elem = mesh.elem_ptr(elem_id);
1070
1071 // The side numberings in libmesh and exodus are not 1:1, so we need to map
1072 // whatever side number is stored in Exodus into a libmesh side number using
1073 // a conv object...
1074 const auto & conv = nemhelper->get_conversion(elem->type());
1075
1076 // Finally, we are ready to add the element and its side to the BoundaryInfo object.
1077 // Call the version of add_side which takes a pointer, since we have already gone to
1078 // the trouble of getting said pointer...
1080 cast_int<unsigned short>(conv.get_side_map(nemhelper->side_list[e]-1)), // Exodus numbering is 1-based
1081 cast_int<boundary_id_type>(nemhelper->id_list[e]));
1082 }
1083
1084 for (const auto & [id, name] : nemhelper->id_to_ss_names)
1085 if (name != "")
1086 mesh.get_boundary_info().sideset_name(id) = name;
1087
1088 // Debugging: make sure there are as many boundary conditions in the
1089 // boundary ID object as expected. Note that, at this point, the
1090 // mesh still thinks it's serial, so n_boundary_conds() returns the
1091 // local number of boundary conditions (and is therefore cheap)
1092 // which should match nemhelper->elem_list.size().
1093 {
1094 std::size_t nbcs = mesh.get_boundary_info().n_boundary_conds();
1095 libmesh_error_msg_if(nbcs != nemhelper->elem_list.size(),
1096 "[" << this->processor_id() << "] "
1097 << "BoundaryInfo contains "
1098 << nbcs
1099 << " boundary conditions, while the Exodus file had "
1100 << nemhelper->elem_list.size());
1101 }
1102
1103 // Read global nodeset parameters? We might be able to use this to verify
1104 // something about the local files, but I haven't figured out what yet...
1105 nemhelper->get_ns_param_global();
1106
1107 // Read local nodeset info
1108 nemhelper->read_nodeset_info();
1109
1110 if (_verbose)
1111 {
1112 libMesh::out << "[" << this->processor_id() << "] ";
1113 libMesh::out << "nemhelper->num_node_sets=" << nemhelper->num_node_sets << std::endl;
1114 if (nemhelper->num_node_sets > 0)
1115 {
1116 libMesh::out << "Nodeset names are: ";
1117 for (const auto & [id, name] : nemhelper->id_to_ns_names)
1118 libMesh::out << "(" << id << "," << name << ") ";
1119 libMesh::out << std::endl;
1120 }
1121 }
1122
1123 // // Debugging, what is currently in nemhelper->node_num_map anyway?
1124 // libMesh::out << "[" << this->processor_id() << "] "
1125 // << "nemhelper->node_num_map = ";
1126 //
1127 // for (const auto & id : nemhelper->node_num_map)
1128 // libMesh::out << id << ", ";
1129 // libMesh::out << std::endl;
1130
1131 // For each nodeset,
1132 for (int nodeset=0; nodeset<nemhelper->num_node_sets; nodeset++)
1133 {
1134 // Get the user-defined ID associated with the nodeset
1135 int nodeset_id = nemhelper->nodeset_ids[nodeset];
1136
1137 if (_verbose)
1138 {
1139 libMesh::out << "[" << this->processor_id() << "] ";
1140 libMesh::out << "nemhelper->nodeset_ids[" << nodeset << "]=" << nodeset_id << std::endl;
1141 }
1142
1143 // Read the nodeset from file, store them in a vector
1144 nemhelper->read_nodeset(nodeset);
1145
1146 // Add nodes from the node_list to the BoundaryInfo object
1147 for (auto node : index_range(nemhelper->node_list))
1148 {
1149 // Don't run past the end of our node map!
1150 libmesh_error_msg_if(to_uint(nemhelper->node_list[node]-1) >= nemhelper->node_num_map.size(),
1151 "Error, index is past the end of node_num_map array!");
1152
1153 // We should be able to use the node_num_map data structure set up previously to determine
1154 // the proper global node index.
1155 unsigned global_node_id = nemhelper->node_num_map[ nemhelper->node_list[node]-1 /*Exodus is 1-based!*/ ]-1;
1156
1157 if (_verbose)
1158 {
1159 libMesh::out << "[" << this->processor_id() << "] "
1160 << "nodeset " << nodeset
1161 << ", local node number: " << nemhelper->node_list[node]-1
1162 << ", global node id: " << global_node_id
1163 << std::endl;
1164 }
1165
1166 // Add the node to the BoundaryInfo object with the proper nodeset_id
1168 (cast_int<dof_id_type>(global_node_id),
1169 cast_int<boundary_id_type>(nodeset_id));
1170 }
1171 }
1172
1173 for (const auto & [id, name] : nemhelper->id_to_ns_names)
1174 if (name != "")
1175 mesh.get_boundary_info().nodeset_name(id) = name;
1176
1177 // See what the elem count is up to now.
1178 if (_verbose)
1179 {
1180 // Report the number of elements which have been added locally
1181 libMesh::out << "[" << this->processor_id() << "] ";
1182 libMesh::out << "mesh.n_elem()=" << mesh.n_elem() << std::endl;
1183
1184 // Reports the number of elements that have been added in total.
1185 libMesh::out << "[" << this->processor_id() << "] ";
1186 libMesh::out << "mesh.parallel_n_elem()=" << mesh.parallel_n_elem() << std::endl;
1187 }
1188
1189 // For DistributedMesh, it seems that _is_serial is true by default. A hack to
1190 // make the Mesh think it's parallel might be to call:
1192 MeshCommunication().make_node_unique_ids_parallel_consistent(mesh);
1194
1195 // If that didn't work, then we're actually reading into a
1196 // ReplicatedMesh, so we want to gather *all* elements
1197 if (mesh.is_serial())
1198 // Don't just use mesh.allgather(); that's a no-op, since
1199 // ReplicatedMesh didn't expect to be distributed in the first
1200 // place!
1201 MeshCommunication().allgather(mesh);
1202 else
1203 // Gather neighboring elements so that a distributed mesh has the
1204 // proper "ghost" neighbor information.
1205 MeshCommunication().gather_neighboring_elements(cast_ref<DistributedMesh &>(mesh));
1206
1207#ifdef LIBMESH_ENABLE_UNIQUE_ID
1208 // We've been setting unique_ids by hand; let's make sure that later
1209 // ones are consistent with them.
1211#endif
1212}
void max(const T &r, T &o, Request &req) const
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
std::size_t n_boundary_conds() const
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
virtual bool is_serial() const
Definition mesh_base.h:357
virtual const Node * node_ptr(const dof_id_type i) const =0
unsigned int mesh_dimension() const
Definition mesh_base.C:430
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
Definition mesh_base.h:423
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual void update_post_partitioning()
Recalculate any cached data (or invalidate any caches that are computed on the fly) after elements an...
Definition mesh_base.C:1180
virtual const Elem * elem_ptr(const dof_id_type i) const =0
virtual void set_next_unique_id(unique_id_type id)=0
Sets the next available unique id to be used.
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
Definition mesh_base.h:399
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
virtual unique_id_type parallel_max_unique_id() const =0
void set_n_partitions(unsigned int n_parts)
Sets the number of partitions in the mesh.
Definition mesh_input.h:101
std::vector< bool > elems_of_dimension
A vector of bools describing what dimension elements have been encountered when reading a mesh.
Definition mesh_input.h:107
Status wait(Request &r)
MPI_Status status
const unsigned int any_source
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
A useful inline function which replaces the macros used previously.
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
void deallocate(std::vector< T > &vec)
A convenient method to truly empty a vector using the "swap trick".
Definition utility.h:345
The libMesh namespace provides an interface to certain functionality in the library.
OStreamProxy err
OStreamProxy out
TestClass subdomain_id_type
Based on the 4-byte comment warning above, this probably doesn't work with exodusII at all....
Definition id_types.h:43
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

References _verbose, libMesh::MeshBase::add_elem(), libMesh::BoundaryInfo::add_node(), libMesh::MeshBase::add_point(), libMesh::BoundaryInfo::add_side(), libMesh::Parallel::Communicator::allgather(), libMesh::MeshCommunication::allgather(), TIMPI::any_source, assert_symmetric_cmaps(), libMesh::Elem::build(), libMesh::ParallelObject::comm(), libMesh::Utility::deallocate(), libMesh::MeshBase::delete_remote_elements(), libMesh::MeshBase::elem_ptr(), libMesh::MeshInput< MeshBase >::elems_of_dimension, libMesh::err, libMesh::MeshCommunication::gather_neighboring_elements(), libMesh::MeshBase::get_boundary_info(), libMesh::Parallel::Communicator::get_unique_tag(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::make_range(), libMesh::Parallel::Communicator::max(), libMesh::MeshInput< MT >::mesh(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::mesh_dimension(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshBase::n_elem(), libMesh::MeshBase::n_nodes(), libMesh::ParallelObject::n_processors(), nemhelper, libMesh::MeshBase::node_ptr(), libMesh::BoundaryInfo::nodeset_name(), libMesh::out, libMesh::MeshBase::parallel_max_unique_id(), libMesh::MeshBase::parallel_n_elem(), libMesh::MeshBase::parallel_n_nodes(), libMesh::ParallelObject::processor_id(), libMesh::Parallel::Communicator::receive(), libMesh::Parallel::Communicator::send(), libMesh::MeshBase::set_mesh_dimension(), libMesh::MeshInput< MeshBase >::set_n_partitions(), libMesh::MeshBase::set_next_unique_id(), libMesh::Elem::set_node(), libMesh::MeshBase::set_subdomain_name(), libMesh::DofObject::set_unique_id(), libMesh::BoundaryInfo::sideset_name(), libMesh::Parallel::Communicator::sum(), libMesh::Elem::type(), libMesh::MeshBase::update_post_partitioning(), and TIMPI::wait().

Referenced by libMesh::NameBasedIO::read(), MeshInputTest::testNemesisReadImpl(), MeshInputTest::testSingleElementImpl(), and WriteVecAndScalar::testWriteNemesis().

◆ read_global_variable()

void libMesh::Nemesis_IO::read_global_variable ( std::vector< std::string >  global_var_names,
unsigned int  timestep,
std::vector< Real > &  global_values 
)

Given a vector of global variables and a time step, returns the values of the global variable at the corresponding time step index.

Parameters
global_var_namesVector of names of global variables
timestepThe corresponding time step index
global_valuesThe vector to be filled

Definition at line 1822 of file nemesis_io.C.

1825{
1826 std::size_t size = global_var_names.size();
1827 libmesh_error_msg_if(size == 0, "ERROR, empty list of global variables to read from the Nemesis file.");
1828
1829 // read the values for all global variables
1830 std::vector<Real> values_from_exodus;
1831 nemhelper->read_var_names(ExodusII_IO_Helper::GLOBAL);
1832 nemhelper->read_global_values(values_from_exodus, timestep);
1833 std::vector<std::string> global_var_names_exodus = nemhelper->global_var_names;
1834
1835 if (values_from_exodus.size() == 0)
1836 return; // This will happen in parallel on procs that are not 0
1837
1838 global_values.clear();
1839 for (std::size_t i = 0; i != size; ++i)
1840 {
1841 // for each global variable in global_var_names, look the corresponding one in global_var_names_from_exodus
1842 // and fill global_values accordingly
1843 auto it = find(global_var_names_exodus.begin(), global_var_names_exodus.end(), global_var_names[i]);
1844 if (it != global_var_names_exodus.end())
1845 global_values.push_back(values_from_exodus[it - global_var_names_exodus.begin()]);
1846 else
1847 libmesh_error_msg("ERROR, Global variable " << global_var_names[i] << \
1848 " not found in Nemesis file.");
1849 }
1850}

References libMesh::ExodusII_IO_Helper::GLOBAL, and nemhelper.

Referenced by copy_scalar_solution().

◆ set_hdf5_writing()

void libMesh::Nemesis_IO::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 1862 of file nemesis_io.C.

1863{
1864 nemhelper->set_hdf5_writing(write_hdf5);
1865}

References nemhelper.

◆ set_n_partitions()

void libMesh::MeshInput< MeshBase >::set_n_partitions ( unsigned int  n_parts)
inlineprotectedinherited

Sets the number of partitions in the mesh.

Typically this gets done by the partitioner, but some parallel file formats begin "pre-partitioned".

Definition at line 101 of file mesh_input.h.

101{ this->mesh().set_n_partitions() = n_parts; }
MeshBase & mesh

◆ set_output_variables()

void libMesh::Nemesis_IO::set_output_variables ( const std::vector< std::string > &  output_variables,
bool  allow_empty = true 
)

Specify the list of variables which should be included in the output (whitelist) If empty, then all variables will be present in the output.

This interface is copied from ExodusII_IO since it was found to be useful there, but perhaps eventually these implementations could somehow be combined.

Definition at line 169 of file nemesis_io.C.

171{
172 _output_variables = output_variables;
173 _allow_empty_variables = allow_empty;
174}
std::vector< std::string > _output_variables
The names of the variables to be output.
Definition nemesis_io.h:295

References _allow_empty_variables, and _output_variables.

◆ skip_comment_lines()

void libMesh::MeshInput< MeshBase >::skip_comment_lines ( std::istream &  in,
const char  comment_start 
)
protectedinherited

Reads input from in, skipping all the lines that start with the character comment_start.

Definition at line 113 of file mesh_input.h.

189{
190 char c, line[256];
191
192 while (in.get(c), c==comment_start)
193 in.getline (line, 255);
194
195 // put back first character of
196 // first non-comment line
197 in.putback (c);
198}

◆ verbose()

void libMesh::Nemesis_IO::verbose ( bool  set_verbosity)

Set the flag indicating if we should be verbose.

Definition at line 139 of file nemesis_io.C.

140{
141 _verbose = set_verbosity;
142
143#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
144 // Set the verbose flag in the helper object
145 // as well.
146 nemhelper->verbose = _verbose;
147#endif
148}

References _verbose, and nemhelper.

◆ write()

void libMesh::Nemesis_IO::write ( const std::string &  base_filename)
overridevirtual

This method implements writing a mesh to a specified file.

Implements libMesh::MeshOutput< MeshBase >.

Definition at line 1229 of file nemesis_io.C.

1230{
1231 // Get a constant reference to the mesh for writing
1232 const MeshBase & mesh = MeshOutput<MeshBase>::mesh();
1233
1234 // Create the filename for this processor given the base_filename passed in.
1235 std::string nemesis_filename = nemhelper->construct_nemesis_filename(base_filename);
1236
1237 // If the user has set the append flag here, it doesn't really make
1238 // sense: the intent of this function is to write a Mesh with no
1239 // data, while "appending" is really intended to add data to an
1240 // existing file. If we're verbose, print a message to this effect.
1241 if (_append && _verbose)
1242 libmesh_warning("Warning: Appending in Nemesis_IO::write() does not make sense.\n"
1243 "Creating a new file instead!");
1244
1245 nemhelper->create(nemesis_filename);
1246
1247 // Initialize data structures and write some global Nemesis-specific data, such as
1248 // communication maps, to file.
1249 nemhelper->initialize(nemesis_filename,mesh);
1250
1251 // Make sure we're writing communication maps we can reuse as
1252 // expected when reading
1253 this->assert_symmetric_cmaps();
1254
1255 // Call the Nemesis-specialized version of write_nodal_coordinates() to write
1256 // the nodal coordinates.
1257 nemhelper->write_nodal_coordinates(mesh);
1258
1259 // Call the Nemesis-specialized version of write_elements() to write
1260 // the elements. Note: Must write a zero if a given global block ID has no
1261 // elements...
1262 nemhelper->write_elements(mesh);
1263
1264 // Call our specialized function to write the nodesets
1265 nemhelper->write_nodesets(mesh);
1266
1267 // Call our specialized write_sidesets() function to write the sidesets to file
1268 nemhelper->write_sidesets(mesh);
1269
1270 // Not sure if this is really necessary, but go ahead and flush the file
1271 // once we have written all this stuff.
1272 nemhelper->update();
1273
1275 libmesh_warning("Warning: Mesh contains edge boundary IDs, but these "
1276 "are not supported by the Nemesis format.");
1277}

References _append, _verbose, assert_symmetric_cmaps(), libMesh::MeshBase::get_boundary_info(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::mesh(), libMesh::BoundaryInfo::n_edge_conds(), and nemhelper.

Referenced by libMesh::ErrorVector::plot_error(), and libMesh::NameBasedIO::write().

◆ write_complex_magnitude()

void libMesh::Nemesis_IO::write_complex_magnitude ( bool  val)

Set the flag indicating whether the complex modulus should be written when complex numbers are enabled.

By default this flag is set to true.

Definition at line 152 of file nemesis_io.C.

153{
154#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
155 nemhelper->write_complex_abs = val;
156#endif
157 libmesh_ignore(val);
158}

References libMesh::libmesh_ignore(), and nemhelper.

◆ write_discontinuous_equation_systems()

void libMesh::MeshOutput< MeshBase >::write_discontinuous_equation_systems ( const std::string &  fname,
const EquationSystems es,
const std::set< std::string > *  system_names = nullptr 
)
virtualinherited

This method implements writing a mesh with discontinuous data to a specified file where the data is taken from the EquationSystems object.

Definition at line 101 of file mesh_output.C.

92{
93 LOG_SCOPE("write_discontinuous_equation_systems()", "MeshOutput");
94
95 // We may need to gather and/or renumber a DistributedMesh to output
96 // it, making that const qualifier in our constructor a dirty lie
97 MT & my_mesh = const_cast<MT &>(*_obj);
98
99 // If we're asked to write data that's associated with a different
100 // mesh, output files full of garbage are the result.
101 libmesh_assert_equal_to(&es.get_mesh(), _obj);
102
103 // A non-renumbered mesh may not have a contiguous numbering, and
104 // that needs to be fixed before we can build a solution vector.
105 if (my_mesh.max_elem_id() != my_mesh.n_elem() ||
106 my_mesh.max_node_id() != my_mesh.n_nodes())
107 {
108 // If we were allowed to renumber then we should have already
109 // been properly renumbered...
110 libmesh_assert(!my_mesh.allow_renumbering());
111
112 libmesh_do_once(libMesh::out <<
113 "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
114 << std::endl;);
115
116 my_mesh.allow_renumbering(true);
117
118 my_mesh.renumber_nodes_and_elements();
119
120 // Not sure what good going back to false will do here, the
121 // renumbering horses have already left the barn...
122 my_mesh.allow_renumbering(false);
123 }
124
125 MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
126
127 // Build the list of variable names that will be written.
128 std::vector<std::string> names;
129 es.build_variable_names (names, nullptr, system_names);
130
131 if (!_is_parallel_format)
132 {
133 // Build the nodal solution values & get the variable
134 // names from the EquationSystems object
135 std::vector<Number> soln;
136 es.build_discontinuous_solution_vector (soln, system_names,
137 nullptr, false, /* defaults */
138 this->get_add_sides());
139
140 this->write_nodal_data_discontinuous (fname, soln, names);
141 }
142 else // _is_parallel_format
143 {
144 libmesh_not_implemented();
145 }
146}
virtual void write_nodal_data_discontinuous(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
This method implements writing a mesh with discontinuous data to a specified file where the nodal dat...

◆ write_element_data()

void libMesh::Nemesis_IO::write_element_data ( const EquationSystems es)

Write out element solution in parallel, without localizing the solution vector.

Note
Unlike write_nodal_data(), this function is not virtual and it does not override anything from the base class. This design is similar to the function by the same name in ExodusII_IO.

Definition at line 1467 of file nemesis_io.C.

1468{
1469 libmesh_error_msg_if(!nemhelper->opened_for_writing,
1470 "ERROR, Nemesis file must be initialized before outputting elemental variables.");
1471
1472 // To be (possibly) filled with a filtered list of variable names to output.
1473 std::vector<std::string> names;
1474
1475 // If _output_variables is populated, find_elemental_data_variable_numbers()
1476 // will filter this list to the variables that can be written as elemental data.
1477 if (_output_variables.size())
1478 names.assign(_output_variables.begin(), _output_variables.end());
1479
1480 // The 'names' vector will here be updated with the variable's names
1481 // that are actually eligible to write
1482 std::vector<std::pair<unsigned int, unsigned int>> var_nums =
1483 es.find_elemental_data_variable_numbers(names);
1484
1485 // find_variable_numbers() can return an empty vector, in which case there are no elemental data
1486 // variables to write, and we can just return.
1487 if (var_nums.empty())
1488 {
1489 if (_verbose)
1490 libMesh::out << "No elemental data variables to be written." << std::endl;
1491 return;
1492 }
1493
1494 // Store the list of subdomains on which each variable *that we are
1495 // going to plot* is active. Note: if any of these sets is _empty_,
1496 // the variable in question is active on _all_ subdomains.
1497 std::vector<std::set<subdomain_id_type>> vars_active_subdomains;
1498 es.get_vars_active_subdomains(names, vars_active_subdomains);
1499
1500 const MeshBase & mesh = MeshOutput<MeshBase>::mesh();
1501
1502#ifdef LIBMESH_USE_COMPLEX_NUMBERS
1503 std::vector<std::string> complex_names =
1504 nemhelper->get_complex_names(names, nemhelper->write_complex_abs);
1505
1506 std::vector<std::set<subdomain_id_type>>
1507 complex_vars_active_subdomains =
1508 nemhelper->get_complex_vars_active_subdomains(vars_active_subdomains,
1509 nemhelper->write_complex_abs);
1510 nemhelper->initialize_element_variables(complex_names, complex_vars_active_subdomains);
1511
1512 // Call (non-virtual) function to write the elemental data in
1513 // parallel. This function is named similarly to the corresponding
1514 // function in the Exodus helper, but it has a different calling
1515 // sequence and is not virtual or an override.
1516 nemhelper->write_element_values(mesh,
1517 es,
1518 var_nums,
1519 _timestep,
1520 complex_vars_active_subdomains);
1521
1522#else
1523 // Call the Nemesis version of initialize_element_variables().
1524 //
1525 // The Exodus helper version of this function writes an incorrect
1526 // truth table in parallel that somehow does not account for the
1527 // case where a subdomain does not appear on one or more of the
1528 // processors. So, we override that function's behavior in the
1529 // Nemesis helper.
1530 nemhelper->initialize_element_variables(names, vars_active_subdomains);
1531
1532 // Call (non-virtual) function to write the elemental data in
1533 // parallel. This function is named similarly to the corresponding
1534 // function in the Exodus helper, but it has a different calling
1535 // sequence and is not virtual or an override.
1536 nemhelper->write_element_values(mesh,
1537 es,
1538 var_nums,
1539 _timestep,
1540 vars_active_subdomains);
1541#endif
1542}

References _output_variables, _timestep, _verbose, libMesh::EquationSystems::find_elemental_data_variable_numbers(), libMesh::EquationSystems::get_vars_active_subdomains(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::mesh(), nemhelper, and libMesh::out.

Referenced by libMesh::ErrorVector::plot_error(), and MeshInputTest::testSingleElementImpl().

◆ write_equation_systems()

void libMesh::MeshOutput< MeshBase >::write_equation_systems ( const std::string &  fname,
const EquationSystems es,
const std::set< std::string > *  system_names = nullptr 
)
virtualinherited

This method implements writing a mesh with data to a specified file where the data is taken from the EquationSystems object.

Reimplemented in libMesh::NameBasedIO, and libMesh::ExodusII_IO.

Definition at line 92 of file mesh_output.C.

34{
35 LOG_SCOPE("write_equation_systems()", "MeshOutput");
36
37 // We may need to gather and/or renumber a DistributedMesh to output
38 // it, making that const qualifier in our constructor a dirty lie
39 MT & my_mesh = const_cast<MT &>(*_obj);
40
41 // If we're asked to write data that's associated with a different
42 // mesh, output files full of garbage are the result.
43 libmesh_assert_equal_to(&es.get_mesh(), _obj);
44
45 // A non-parallel format, non-renumbered mesh may not have a contiguous
46 // numbering, and that needs to be fixed before we can build a solution vector.
47 if (!_is_parallel_format &&
48 (my_mesh.max_elem_id() != my_mesh.n_elem() ||
49 my_mesh.max_node_id() != my_mesh.n_nodes()))
50 {
51 // If we were allowed to renumber then we should have already
52 // been properly renumbered...
53 libmesh_assert(!my_mesh.allow_renumbering());
54
55 libmesh_do_once(libMesh::out <<
56 "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
57 << std::endl;);
58
59 my_mesh.allow_renumbering(true);
60
61 my_mesh.renumber_nodes_and_elements();
62
63 // Not sure what good going back to false will do here, the
64 // renumbering horses have already left the barn...
65 my_mesh.allow_renumbering(false);
66 }
67
68 if (!_is_parallel_format)
69 {
70 MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
71
72 // Build the list of variable names that will be written.
73 std::vector<std::string> names;
74 es.build_variable_names (names, nullptr, system_names);
75
76 // Build the nodal solution values & get the variable
77 // names from the EquationSystems object
78 std::vector<Number> soln;
79 es.build_solution_vector (soln, system_names,
80 this->get_add_sides());
81
82 this->write_nodal_data (fname, soln, names);
83 }
84 else // _is_parallel_format
85 this->write_nodal_data (fname, es, system_names);
86}
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...

◆ write_global_data()

void libMesh::Nemesis_IO::write_global_data ( const std::vector< Number > &  soln,
const std::vector< std::string > &  names 
)

Write out global variables.

Definition at line 1584 of file nemesis_io.C.

1586{
1587 libmesh_error_msg_if(!nemhelper->opened_for_writing,
1588 "ERROR, Nemesis file must be initialized before outputting global variables.");
1589
1590#ifdef LIBMESH_USE_COMPLEX_NUMBERS
1591
1592 std::vector<std::string> complex_names =
1593 nemhelper->get_complex_names(names, nemhelper->write_complex_abs);
1594
1595 nemhelper->initialize_global_variables(complex_names);
1596
1597 unsigned int num_values = soln.size();
1598 unsigned int num_vars = names.size();
1599 unsigned int num_elems = num_values / num_vars;
1600
1601 // This will contain the real and imaginary parts and the magnitude
1602 // of the values in soln
1603 int nco = nemhelper->write_complex_abs ? 3 : 2;
1604 std::vector<Real> complex_soln(nco * num_values);
1605
1606 for (unsigned i=0; i<num_vars; ++i)
1607 {
1608 for (unsigned int j=0; j<num_elems; ++j)
1609 {
1610 Number value = soln[i*num_vars + j];
1611 complex_soln[nco*i*num_elems + j] = value.real();
1612 }
1613 for (unsigned int j=0; j<num_elems; ++j)
1614 {
1615 Number value = soln[i*num_vars + j];
1616 complex_soln[nco*i*num_elems + num_elems + j] = value.imag();
1617 }
1618 if (nemhelper->write_complex_abs)
1619 {
1620 for (unsigned int j=0; j<num_elems; ++j)
1621 {
1622 Number value = soln[i*num_vars + j];
1623 complex_soln[3*i*num_elems + 2*num_elems + j] = std::abs(value);
1624 }
1625 }
1626 }
1627
1628 nemhelper->write_global_values(complex_soln, _timestep);
1629
1630#else
1631
1632 // Call the Exodus writer implementation
1633 nemhelper->initialize_global_variables( names );
1634 nemhelper->write_global_values( soln, _timestep);
1635
1636#endif
1637
1638}
static const bool value
Definition xdr_io.C:55

References _timestep, nemhelper, and value.

◆ write_information_records()

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

Write out information records.

Definition at line 1654 of file nemesis_io.C.

1655{
1656 libmesh_error_msg_if(!nemhelper->opened_for_writing,
1657 "ERROR, Nemesis file must be initialized before outputting information records.");
1658
1659 // Call the Exodus writer implementation
1660 nemhelper->write_information_records( records );
1661}

References nemhelper.

◆ write_nodal_data() [1/3]

void libMesh::Nemesis_IO::write_nodal_data ( const std::string &  fname,
const EquationSystems es,
const std::set< std::string > *  system_names 
)
overridevirtual

Output a nodal solution from EquationSystems current_local_solutions.

Reimplemented from libMesh::MeshOutput< MeshBase >.

Definition at line 1418 of file nemesis_io.C.

1421{
1422 LOG_SCOPE("write_nodal_data(parallel)", "Nemesis_IO");
1423
1424 // Only prepare and write nodal variables that are also in
1425 // _output_variables, unless _output_variables is empty. This is the
1426 // same logic that is in ExodusII_IO::write_nodal_data().
1427 std::vector<std::string> output_names;
1428
1430 output_names = _output_variables;
1431 else
1432 es.build_variable_names (output_names, nullptr, system_names);
1433
1434 this->prepare_to_write_nodal_data(base_filename, output_names);
1435
1436 std::vector<std::pair<unsigned int, unsigned int>> var_nums;
1437 // If we pass in an empty vector below, it will return all of the
1438 // var nums in es, which we don't want.
1439 if (!output_names.empty())
1440 var_nums = es.find_variable_numbers(output_names);
1441
1442 nemhelper->write_nodal_solution(es, var_nums, _timestep, output_names);
1443}
void prepare_to_write_nodal_data(const std::string &fname, const std::vector< std::string > &names)
Helper function containing code shared between the two different versions of write_nodal_data which t...

References _allow_empty_variables, _output_variables, _timestep, libMesh::EquationSystems::build_variable_names(), libMesh::EquationSystems::find_variable_numbers(), nemhelper, and prepare_to_write_nodal_data().

◆ write_nodal_data() [2/3]

void libMesh::Nemesis_IO::write_nodal_data ( const std::string &  fname,
const NumericVector< Number > &  parallel_soln,
const std::vector< std::string > &  names 
)
overridevirtual

Output a nodal solution in parallel, without localizing the soln vector.

Reimplemented from libMesh::MeshOutput< MeshBase >.

Definition at line 1393 of file nemesis_io.C.

1396{
1397 LOG_SCOPE("write_nodal_data(parallel)", "Nemesis_IO");
1398
1399 // Only prepare and write nodal variables that are also in
1400 // _output_variables, unless _output_variables is empty. This is the
1401 // same logic that is in ExodusII_IO::write_nodal_data().
1402 std::vector<std::string> output_names;
1403
1405 output_names = _output_variables;
1406 else
1407 output_names = names;
1408
1409 this->prepare_to_write_nodal_data(base_filename, output_names);
1410
1411 // Call the new version of write_nodal_solution() that takes a
1412 // NumericVector directly without localizing.
1413 nemhelper->write_nodal_solution(parallel_soln, names, _timestep, output_names);
1414}

References _allow_empty_variables, _output_variables, _timestep, nemhelper, and prepare_to_write_nodal_data().

◆ write_nodal_data() [3/3]

void libMesh::Nemesis_IO::write_nodal_data ( const std::string &  fname,
const std::vector< Number > &  soln,
const std::vector< std::string > &  names 
)
overridevirtual

Output a nodal solution from data in soln.

Reimplemented from libMesh::MeshOutput< MeshBase >.

Definition at line 1557 of file nemesis_io.C.

1560{
1561 LOG_SCOPE("write_nodal_data(serialized)", "Nemesis_IO");
1562
1563 this->prepare_to_write_nodal_data(base_filename, names);
1564
1565 nemhelper->write_nodal_solution(soln, names, _timestep);
1566}

References _timestep, nemhelper, and prepare_to_write_nodal_data().

Referenced by libMesh::NameBasedIO::write_nodal_data().

◆ write_nodal_data_discontinuous()

virtual void libMesh::MeshOutput< MeshBase >::write_nodal_data_discontinuous ( const std::string &  ,
const std::vector< Number > &  ,
const std::vector< std::string > &   
)
inlinevirtualinherited

This method implements writing a mesh with discontinuous data to a specified file where the nodal data and variables names are provided.

Reimplemented in libMesh::ExodusII_IO.

Definition at line 118 of file mesh_output.h.

121 { libmesh_not_implemented(); }

◆ write_timestep()

void libMesh::Nemesis_IO::write_timestep ( const std::string &  fname,
const EquationSystems es,
const int  timestep,
const Real  time 
)

Write one timestep's worth of the solution.

Definition at line 1291 of file nemesis_io.C.

1295{
1296 _timestep=timestep;
1297 write_equation_systems(fname,es);
1298
1299 nemhelper->write_timestep(timestep, time);
1300}
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
Definition mesh_output.C:31

References _timestep, nemhelper, and libMesh::MeshOutput< MeshBase >::write_equation_systems().

Member Data Documentation

◆ _allow_empty_variables

bool libMesh::Nemesis_IO::_allow_empty_variables
private

If true, _output_variables is allowed to remain empty.

If false, if _output_variables is empty it will be populated with a complete list of all variables By default, calling set_output_variables() sets this flag to true, but it provides an override.

Definition at line 302 of file nemesis_io.h.

Referenced by set_output_variables(), write_nodal_data(), and write_nodal_data().

◆ _append

bool libMesh::Nemesis_IO::_append
private

Default false.

If true, files will be opened with EX_WRITE rather than created from scratch when writing.

Definition at line 281 of file nemesis_io.h.

Referenced by append(), prepare_to_write_nodal_data(), and write().

◆ _ascii_precision

unsigned int libMesh::MeshOutput< MeshBase >::_ascii_precision
privateinherited

Precision to use when writing ASCII files.

Definition at line 207 of file mesh_output.h.

◆ _communicator

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

◆ _is_parallel_format [1/2]

const bool libMesh::MeshInput< MeshBase >::_is_parallel_format
privateinherited

Flag specifying whether this format is parallel-capable.

If this is false (default) I/O is only permitted when the mesh has been serialized.

Definition at line 130 of file mesh_input.h.

◆ _is_parallel_format [2/2]

const bool libMesh::MeshOutput< MeshBase >::_is_parallel_format
protectedinherited

Flag specifying whether this format is parallel-capable.

If this is false (default) I/O is only permitted when the mesh has been serialized.

Definition at line 184 of file mesh_output.h.

◆ _obj

MeshBase * libMesh::MeshInput< MeshBase >::_obj
privateinherited

A pointer to a non-const object object.

This allows us to read the object from file.

Definition at line 123 of file mesh_input.h.

◆ _output_variables

std::vector<std::string> libMesh::Nemesis_IO::_output_variables
private

The names of the variables to be output.

If this is empty then all variables are output.

Definition at line 295 of file nemesis_io.h.

Referenced by set_output_variables(), write_element_data(), write_nodal_data(), and write_nodal_data().

◆ _serial_only_needed_on_proc_0

const bool libMesh::MeshOutput< MeshBase >::_serial_only_needed_on_proc_0
protectedinherited

Flag specifying whether this format can be written by only serializing the mesh to processor zero.

If this is false (default) the mesh will be serialized to all processors

Definition at line 193 of file mesh_output.h.

◆ _timestep

int libMesh::Nemesis_IO::_timestep
private

Keeps track of the current timestep index being written.

Used when calling write_nodal_data() and other functions.

Definition at line 269 of file nemesis_io.h.

Referenced by write_element_data(), write_global_data(), write_nodal_data(), write_nodal_data(), write_nodal_data(), and write_timestep().

◆ _verbose

bool libMesh::Nemesis_IO::_verbose
private

Controls whether extra debugging information is printed to the screen or not.

Definition at line 275 of file nemesis_io.h.

Referenced by prepare_to_write_nodal_data(), read(), verbose(), write(), and write_element_data().

◆ elems_of_dimension

std::vector<bool> libMesh::MeshInput< MeshBase >::elems_of_dimension
protectedinherited

A vector of bools describing what dimension elements have been encountered when reading a mesh.

Definition at line 107 of file mesh_input.h.

◆ nemhelper

std::unique_ptr<Nemesis_IO_Helper> libMesh::Nemesis_IO::nemhelper
private

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