21 #if defined(__clang__) && __clang_major__ < 12 22 #define RESTARTABLE_SKIP_CHECK_HASH_CODE 30 _error_on_different_number_of_processors(true),
36 std::vector<RestartableDataMap> & data,
40 _error_on_different_number_of_processors(true),
47 std::unique_ptr<std::stringstream> data_stream)
51 _streams.
header = std::make_unique<StringInputStream>(std::move(header_stream));
52 _streams.
data = std::make_unique<StringInputStream>(std::move(data_stream));
74 std::vector<std::unordered_map<std::string, RestartableDataReader::HeaderEntry>>
77 std::vector<std::unordered_map<std::string, RestartableDataReader::HeaderEntry>> header;
79 auto stream_ptr = header_input.
get();
80 auto & stream = *stream_ptr;
84 const auto error = [&header_input](
auto... args)
86 std::stringstream err_prefix;
87 err_prefix <<
"While reading restartable data in ";
90 err_prefix << std::filesystem::absolute(filename->parent_path());
92 err_prefix <<
"memory";
93 err_prefix <<
":\n\n";
100 stream.read(this_id, 2);
101 if (this_id[0] !=
'R' || this_id[1] !=
'D')
102 error(
"The data is invalid or corrupted (unexpected header)");
105 std::remove_const<decltype(CURRENT_BACKUP_FILE_VERSION)>::type this_file_version;
106 dataLoad(stream, this_file_version,
nullptr);
108 error(
"There is a mismatch in the backup version\n\n",
109 "Current backup version: ",
111 "\nLoaded backup version: ",
115 std::size_t this_compare_hash_code;
116 dataLoad(stream, this_compare_hash_code,
nullptr);
117 #ifndef RESTARTABLE_SKIP_CHECK_HASH_CODE 119 error(
"The backup is not compatible\n\nThe hash code check for a basic type (",
120 MooseUtils::prettyCppType<COMPARE_HASH_CODE_TYPE>(),
121 ") failed.\nIt is possible that this backup was stored with a different architecture or " 122 "operating system.\n\nTo forcefully attempt loading the backup, use the command line " 123 "option --force-restart");
130 dataLoad(stream, this_n_procs,
nullptr);
132 error(
"The number of MPI ranks is not consistent\n\nCurrent MPI ranks: ",
134 "\nLoaded MPI ranks: ",
138 decltype(
dataSize()) this_num_data = 0;
139 dataLoad(stream, this_num_data,
nullptr);
141 error(
"The number of threads is not consistent\n\nCurrent threads: ",
143 "\nLoaded threads: ",
149 std::vector<std::size_t> tid_n_data(
dataSize());
151 dataLoad(stream, tid_n_data[tid],
nullptr);
154 std::size_t current_data_position = 0;
158 for (
const auto i :
make_range(tid_n_data[tid]))
164 mooseAssert(
name.size(),
"Empty name");
166 mooseAssert(!header[tid].count(
name),
"Data '" +
name +
"' is already inserted");
167 auto & entry = header[tid][
name];
169 dataLoad(stream, entry.size,
nullptr);
170 dataLoad(stream, entry.type_hash_code,
nullptr);
171 dataLoad(stream, entry.type,
nullptr);
172 dataLoad(stream, entry.has_context,
nullptr);
173 entry.position = current_data_position;
175 current_data_position += entry.size;
187 mooseError(
"RestartableDataReader::restore(): Cannot restore because an input was not set");
194 value.setNotLoaded({});
202 const auto & header =
_header[tid];
206 for (
auto &
value : data)
210 auto find_header = header.find(
name);
211 if (find_header == header.end())
214 auto & header_entry = find_header->second;
217 const auto is_data_in_filter = filter_names.find(
name) != filter_names.end();
218 if (!is_data_in_filter)
226 const std::type_info & type,
229 if (
const auto header =
queryHeader(data_name, tid))
238 const auto it =
_header[tid].find(data_name);
250 "RestartableDataReader::getHeader(): Failed to find a header entry for data with name '",
262 mooseAssert(!
value.loaded(),
value.name() +
" is already loaded");
264 auto error = [&data_input, &
value](
auto... args)
266 std::stringstream
err;
267 err <<
"While loading restartable data\n\n";
271 err << std::filesystem::absolute(filename->parent_path());
274 err <<
"\nData name: " <<
value.name();
275 err <<
"\nData type: " <<
value.type();
281 error(
"The stored type of '", header_entry.
type,
"' does not match");
283 auto stream_ptr = data_input.
get();
284 auto & stream = *stream_ptr;
286 stream.seekg(header_entry.
position);
289 if (stream.tellg() == -1)
290 error(
"An error was encountered when reading from the stream");
292 const std::size_t loaded_size = stream.tellg() - header_entry.
position;
293 if (loaded_size != header_entry.
size)
294 error(
"The data read does not match the data stored\n\n",
307 const auto available = [](
const auto & filename)
310 const bool header_available = available(header_path);
311 const bool data_available = available(data_path);
313 if (header_available != data_available)
315 header_available ?
"header" :
"data",
316 " is available but the corresponding ",
317 header_available ?
"data" :
"header",
318 " is not available\n\n",
320 header_available ?
"available" :
"missing",
322 std::filesystem::absolute(header_path),
324 data_available ?
"available" :
"missing",
326 std::filesystem::absolute(header_path));
328 return header_available && data_available;
336 "The RestartableDataReader is not available for querying as it is not currently restoring");
343 const std::type_info & type)
const 345 #ifndef RESTARTABLE_SKIP_CHECK_HASH_CODE 349 return header_entry.
type == type.name();
354 std::unique_ptr<RestartableDataValue> value,
358 if (data_map.hasData(data_name))
359 mooseError(
"RestartableDataReader::restoreData(): Cannot declare restartable data '",
361 "' because it has already been declared");
363 const auto & header =
getHeader(data_name, tid);
std::string name(const ElemQuality q)
static const std::string & restartableDataFile()
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
void setInput(std::unique_ptr< std::stringstream > header_stream, std::unique_ptr< std::stringstream > data_stream)
Sets the input stream for reading from the stringstreams header_stream and data_stream for the header...
void requireRestoring() const
Checks whether or not we're currently restoring and errors if not.
void swap(std::vector< T > &data, const std::size_t idx0, const std::size_t idx1, const libMesh::Parallel::Communicator &comm)
Swap function for serial or distributed vector of data.
static const unsigned int CURRENT_BACKUP_FILE_VERSION
The current version for the backup file.
std::size_t dataSize() const
static const std::string & restartableHeaderFile()
Base class for MOOSE-based applications.
const HeaderEntry & getHeader(const std::string &data_name, const THREAD_ID tid) const
void dataLoad(std::istream &stream, PenetrationInfo *&pinfo, void *context)
int COMPARE_HASH_CODE_TYPE
The type to used for comparing hash codes (sanity checking)
RestartableDataValue & addData(std::unique_ptr< RestartableDataValue > data)
Adds the restartable data data to the map.
std::vector< std::unordered_map< std::string, HeaderEntry > > readHeader(InputStream &header_input) const
Internal method for reading the header (stored by RestartableDataWriter)
RestartableDataMap & currentData(const THREAD_ID tid)
Storage for restartable data that is ordered based on insertion order.
const HeaderEntry * queryHeader(const std::string &data_name, const THREAD_ID tid) const
processor_id_type n_processors() const
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
bool checkFileReadable(const std::string &filename, bool check_line_endings=false, bool throw_on_unreadable=true, bool check_for_git_lfs_pointer=true)
Checks to see if a file is readable (exists and permissions)
bool isSameType(const HeaderEntry &header_entry, const std::type_info &type) const
RestartableDataReader(MooseApp &app, RestartableDataMap &data, const bool force=false)
T & restoreData(const std::string &data_name, const THREAD_ID tid=0, void *const context=nullptr, Args &&... args)
Restores the data with name data_name of type T.
bool _is_restoring
Whether or not we're currently restoring.
const bool _force
Whether or not to forcefully attempt to read despite incompatibilities.
bool hasData(const std::string &data_name, const THREAD_ID tid=0) const
void deserializeValue(InputStream &data_input, RestartableDataValue &value, const HeaderEntry &header_entry) const
Internal method for deserializing (restoring from backup into a value)
IntRange< T > make_range(T beg, T end)
std::unordered_set< std::string > DataNames
class infix_ostream_iterator if void
bool _error_on_different_number_of_processors
Whether or not to error with a different number of processors.
InputStreams clear()
Clears the contents of the reader (header stream, data stream, header)
void restore(const DataNames &filter_names={})
Restores the restartable data.
InputStreams _streams
The inputs for reading.
bool pathExists(const std::string &path)
auto index_range(const T &sizable)
Abstract definition of a RestartableData value.
std::vector< std::unordered_map< std::string, HeaderEntry > > _header
The loaded headers from the restart.
static bool isAvailable(const std::filesystem::path &folder_base)