Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions include/base/libmesh_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,32 @@ inline Tnew libmesh_cast_int (Told oldvar)
return cast_int<Tnew>(oldvar);
}


/**
* restrict_int checks that the value of the castee is within the
* bounds which are exactly representable by the output type, even in
* optimized modes.
*
* Use this cast when you suspect that the input may not succeed in
* correct code (e.g. when an input file is being read from a format
* that may allow wider integer types than the current libMesh
* configuration).
*/
template <typename Tnew, typename Told>
inline Tnew restrict_int (Told oldvar)
{
if constexpr (!std::is_same_v<Tnew, Told>)
{
const Tnew returnval = static_cast<Tnew>(oldvar);

libmesh_error_msg_if (oldvar != static_cast<Told>(returnval),
"restrict_int failed: " << oldvar << " does not fit in type " << typeid(returnval).name());
}

return oldvar;
}


/**
* This is a helper variable template for cases when we want to use a default compile-time
* error with constexpr-based if conditions. The templating delays the triggering
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/checkpoint_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ void CheckpointIO::read_connectivity (Xdr & io)
cast_int<processor_id_type>
(elem_data[2] % mesh.n_processors());
const subdomain_id_type subdomain_id =
cast_int<subdomain_id_type>(elem_data[3]);
restrict_int<subdomain_id_type>(elem_data[3]);

// Old broken files used processsor_id_type(-1)...
// But we *know* our first element will be level 0
Expand Down
9 changes: 5 additions & 4 deletions src/mesh/exodusII_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ void ExodusII_IO::read (const std::string & fname)

// We'll set any spline NodeElem subdomain_id() values to exceed the
// maximum of subdomain_id() values set via Exodus block ids.
int max_subdomain_id = std::numeric_limits<int>::min();
subdomain_id_type max_subdomain_id = std::numeric_limits<subdomain_id_type>::min();

// We've already added all the nodes explicitly specified in the
// file, but if we have spline nodes we may need to add assembly
Expand All @@ -440,13 +440,14 @@ void ExodusII_IO::read (const std::string & fname)
{
// Read the information for block i
exio_helper->read_elem_in_block (i);
const int subdomain_id = exio_helper->get_block_id(i);
const subdomain_id_type subdomain_id =
restrict_int<subdomain_id_type>(exio_helper->get_block_id(i));
max_subdomain_id = std::max(max_subdomain_id, subdomain_id);

// populate the map of names
std::string subdomain_name = exio_helper->get_block_name(i);
if (!subdomain_name.empty())
mesh.subdomain_name(static_cast<subdomain_id_type>(subdomain_id)) = subdomain_name;
mesh.subdomain_name(subdomain_id) = subdomain_name;

// Set any relevant node/edge maps for this element
const std::string type_str (exio_helper->get_elem_type());
Expand All @@ -473,7 +474,7 @@ void ExodusII_IO::read (const std::string & fname)
<< " has " << uelem->n_nodes() << " nodes.");

// Assign the current subdomain to this Elem
uelem->subdomain_id() = static_cast<subdomain_id_type>(subdomain_id);
uelem->subdomain_id() = subdomain_id;

// Determine the libmesh elem id implied by "j". The
// ExodusII_IO_Helper::get_libmesh_elem_id() helper function
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/exodusII_io_helper.C
Original file line number Diff line number Diff line change
Expand Up @@ -3435,7 +3435,7 @@ void ExodusII_IO_Helper::initialize_element_variables(std::vector<std::string> n
std::set<subdomain_id_type> current_set;
if (vars_active_subdomains[var_num].empty())
for (auto block_id : block_ids)
current_set.insert(cast_int<subdomain_id_type>(block_id));
current_set.insert(restrict_int<subdomain_id_type>(block_id));
else
current_set = vars_active_subdomains[var_num];

Expand Down
6 changes: 3 additions & 3 deletions src/mesh/gmsh_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,12 @@ void GmshIO::read_mesh(std::istream & in)
// conditions.
if (s.find("lower_dimensional_block") != std::string::npos)
{
lower_dimensional_blocks.insert(cast_int<subdomain_id_type>(phys_id));
lower_dimensional_blocks.insert(restrict_int<subdomain_id_type>(phys_id));

// The user has explicitly told us that this
// block is a subdomain, so set that association
// in the Mesh.
mesh.subdomain_name(cast_int<subdomain_id_type>(phys_id)) = phys_name;
mesh.subdomain_name(restrict_int<subdomain_id_type>(phys_id)) = phys_name;
}
}
}
Expand Down Expand Up @@ -795,7 +795,7 @@ void GmshIO::read_mesh(std::istream & in)
// If the physical's dimension matches the largest
// dimension we've seen, it's a subdomain name.
if (phys_dim == max_elem_dimension_seen)
mesh.subdomain_name(cast_int<subdomain_id_type>(phys_id)) = phys_name;
mesh.subdomain_name(restrict_int<subdomain_id_type>(phys_id)) = phys_name;

// If it's zero-dimensional then it's a nodeset
else if (phys_dim == 0)
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/nemesis_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ void Nemesis_IO::read (const std::string & base_filename)

// Set subdomain ID based on the block ID.
subdomain_id_type subdomain_id =
cast_int<subdomain_id_type>(nemhelper->block_ids[i]);
restrict_int<subdomain_id_type>(nemhelper->block_ids[i]);

// Create a type string (this uses the null-terminated string ctor).
const std::string type_str ( nemhelper->elem_type.data() );
Expand Down
4 changes: 2 additions & 2 deletions src/mesh/nemesis_io_helper.C
Original file line number Diff line number Diff line change
Expand Up @@ -2285,7 +2285,7 @@ void Nemesis_IO_Helper::write_elements(const MeshBase & mesh, bool /*use_discont
// empty string if there is no name associated with the current
// block.
names_table.push_back_entry
(mesh.subdomain_name(cast_int<subdomain_id_type>(this->global_elem_blk_ids[i])));
(mesh.subdomain_name(restrict_int<subdomain_id_type>(this->global_elem_blk_ids[i])));

// Search for the current global block ID in the map
if (const auto it = this->block_id_to_elem_connectivity.find( this->global_elem_blk_ids[i] );
Expand Down Expand Up @@ -2661,7 +2661,7 @@ Nemesis_IO_Helper::write_element_values(const MeshBase & mesh,
for (const int sbd_id_int : global_elem_blk_ids)
{
const subdomain_id_type sbd_id =
cast_int<subdomain_id_type>(sbd_id_int);
restrict_int<subdomain_id_type>(sbd_id_int);
auto it = subdomain_map.find(sbd_id);
const std::vector<dof_id_type> empty_vec;
const std::vector<dof_id_type> & elem_ids =
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/tetgen_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ void TetGenIO::element_in (std::istream & ele_stream)

// Make sure that the id we read can be successfully cast to
// an integral value of type subdomain_id_type.
elem->subdomain_id() = cast_int<subdomain_id_type>(region);
elem->subdomain_id() = restrict_int<subdomain_id_type>(region);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/ucd_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ void UCDIO::read_implementation (std::istream & in)
elems_of_dimension[elem->dim()] = true;

// Set the element's subdomain ID based on the material_id.
elem->subdomain_id() = cast_int<subdomain_id_type>(material_id);
elem->subdomain_id() = restrict_int<subdomain_id_type>(material_id);

// Add the element to the mesh
elem->set_id(i);
Expand Down
4 changes: 2 additions & 2 deletions src/mesh/unv_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ void UNVIO::groups_in (std::istream & in_file)
// Set the current group number as the lower-dimensional element's subdomain ID.
// We will use this later to set a boundary ID.
group_elem->subdomain_id() =
cast_int<subdomain_id_type>(group_number);
restrict_int<subdomain_id_type>(group_number);

// Store the lower-dimensional element in the provide_bcs container.
provide_bcs.emplace(group_elem->key(), group_elem);
Expand All @@ -530,7 +530,7 @@ void UNVIO::groups_in (std::istream & in_file)
{
is_subdomain_group = true;
group_elem->subdomain_id() =
cast_int<subdomain_id_type>(group_number);
restrict_int<subdomain_id_type>(group_number);
}

else
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/xdr_io.C
Original file line number Diff line number Diff line change
Expand Up @@ -1897,7 +1897,7 @@ XdrIO::read_serialized_connectivity (Xdr & io,
cast_int<processor_id_type>(*it++);

const subdomain_id_type subdomain_id =
cast_int<subdomain_id_type>(*it++);
restrict_int<subdomain_id_type>(*it++);

tmp = *it++;
#ifdef LIBMESH_ENABLE_AMR
Expand Down