@@ -2131,6 +2131,77 @@ void ExodusII_IO_Helper::read_elemental_var_values(std::string elemental_var_nam
21312131
21322132
21332133
2134+ std ::vector < std ::map < dof_id_type , dof_id_type >>
2135+ ExodusII_IO_Helper ::read_extra_integers
2136+ (const std ::vector < std ::string > & extra_integer_var_names )
2137+ {
2138+ std ::vector < std ::map < dof_id_type , dof_id_type >>
2139+ extra_integer_values (extra_integer_var_names .size ());
2140+
2141+ if (extra_integer_var_names .empty ())
2142+ return extra_integer_values ;
2143+
2144+ // Make sure we have an up-to-date count of the number of time steps in the file.
2145+ this -> read_num_time_steps ();
2146+
2147+ // Prepare to check if each real number is outside of the
2148+ // range we can convert exactly
2149+
2150+ const int exodus_digits = _single_precision ?
2151+ std ::numeric_limits < float > ::digits :
2152+ std ::numeric_limits < double > ::digits ;
2153+
2154+ const int shift = std ::min (std ::numeric_limits < Real > ::digits ,
2155+ exodus_digits );
2156+
2157+ const long long max_representation = 1LL << shift ;
2158+
2159+ for (auto i : index_range (extra_integer_var_names ))
2160+ {
2161+ std ::map < dof_id_type , Real > raw_vals ;
2162+
2163+ // Read element extra "integers" as doubles from the last time step
2164+ this -> read_elemental_var_values (extra_integer_var_names [i ], this -> num_time_steps , raw_vals );
2165+
2166+ // Convert doubles to actual integers, at least within the
2167+ // largest convex subset of doubles where this is a bijection.
2168+ auto & values = extra_integer_values [i ];
2169+
2170+ for (auto [elem_id , extra_val ] : raw_vals )
2171+ {
2172+ if (extra_val == Real (-1 ))
2173+ {
2174+ values [elem_id ] = DofObject ::invalid_id ;
2175+ continue ;
2176+ }
2177+
2178+ // Ignore FE_INVALID here even if we've enabled FPEs; a
2179+ // thrown exception is preferred over an FPE signal.
2180+ FPEDisabler disable_fpes ;
2181+ const long long int_val = std ::llround (extra_val );
2182+
2183+ libmesh_error_msg_if (int_val > max_representation ,
2184+ "Error! An element integer value higher than "
2185+ << max_representation
2186+ << " was found! Exodus uses real numbers for storing element "
2187+ " integers, which can only represent integers from 0 to "
2188+ << max_representation << "." );
2189+
2190+ libmesh_error_msg_if (int_val < 0 ,
2191+ "Error! An element integer value less than -1"
2192+ << " was found! Exodus uses real numbers for storing element "
2193+ " integers, which can only represent integers from 0 to "
2194+ << max_representation << "." );
2195+
2196+ values [elem_id ] = cast_int < dof_id_type > (int_val );
2197+ }
2198+ }
2199+
2200+ return extra_integer_values ;
2201+ }
2202+
2203+
2204+
21342205dof_id_type ExodusII_IO_Helper ::get_libmesh_node_id (int exodus_node_id )
21352206{
21362207 return this -> get_libmesh_id (exodus_node_id , this -> node_num_map );
0 commit comments