https://mooseframework.inl.gov
RestartableDataWriter.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "RestartableDataWriter.h"
11 
12 #include "DataIO.h"
13 #include "RestartableDataMap.h"
14 
15 #include <fstream>
16 #include <system_error>
17 
19  : RestartableDataIO(app, data)
20 {
21 }
22 
23 RestartableDataWriter::RestartableDataWriter(MooseApp & app, std::vector<RestartableDataMap> & data)
24  : RestartableDataIO(app, data)
25 {
26 }
27 
28 void
29 RestartableDataWriter::write(std::ostream & header_stream, std::ostream & data_stream)
30 {
31  // Set everything as not stored
32  for (const auto tid : make_range(dataSize()))
33  for (auto & value : currentData(tid))
34  value.setNotStored({});
35 
36  // Header
37  char id[] = {'R', 'D'};
38  header_stream.write(id, 2);
39 
40  // File version
41  auto file_version = CURRENT_BACKUP_FILE_VERSION;
42  dataStore(header_stream, file_version, nullptr);
43 
44  // Type hash for basic hash
45  std::size_t compare_hash_code = typeid(COMPARE_HASH_CODE_TYPE).hash_code();
46  dataStore(header_stream, compare_hash_code, nullptr);
47 
48  // Number of procs
49  auto n_procs = n_processors();
50  dataStore(header_stream, n_procs, nullptr);
51 
52  // Number of data
53  auto num_data = dataSize();
54  dataStore(header_stream, num_data, nullptr);
55 
56  // Size of data for each thread
57  for (const auto tid : make_range(dataSize()))
58  {
59  std::size_t n_data = currentData(tid).size();
60  dataStore(header_stream, n_data, nullptr);
61  }
62 
63  // Write out the RestartableData header, and store the actual data separately
64  for (const auto tid : make_range(dataSize()))
65  for (auto & data : currentData(tid))
66  {
67  // Store the data
68  const std::size_t data_start_position = static_cast<std::size_t>(data_stream.tellp());
69  data.store(data_stream);
70  std::size_t data_size = static_cast<std::size_t>(data_stream.tellp()) - data_start_position;
71 
72  // Store name, size, type hash, and type in the header
73  mooseAssert(data.name().size(), "Empty name");
74  std::string name = data.name();
75  std::string type = data.typeId().name();
76  std::size_t type_hash_code = data.typeId().hash_code();
77  bool has_context = data.hasContext();
78  dataStore(header_stream, name, nullptr);
79  dataStore(header_stream, data_size, nullptr);
80  dataStore(header_stream, type_hash_code, nullptr);
81  dataStore(header_stream, type, nullptr);
82  dataStore(header_stream, has_context, nullptr);
83  }
84 }
85 
86 std::vector<std::filesystem::path>
87 RestartableDataWriter::write(const std::filesystem::path & folder_base)
88 {
89  const auto header_file = restartableHeaderFile(folder_base);
90  const auto data_file = restartableDataFile(folder_base);
91 
92  // Make the folder if it doesn't exist
93  const auto dir = header_file.parent_path();
94  mooseAssert(dir == data_file.parent_path(), "Inconsistent directories");
95  if (!std::filesystem::exists(dir))
96  {
97  std::error_code err;
98  if (!std::filesystem::create_directory(dir, err))
99  mooseError("Unable to create restart directory\n",
100  std::filesystem::absolute(dir),
101  "\n\n",
102  err.message());
103  }
104 
105  // We want to keep track of the paths that we create so that we can
106  // return them for file management later (primarily removing old checkpoints)
107  std::vector<std::filesystem::path> paths;
108 
109  // Helper for opening a stream for use
110  auto open = [&paths](const std::filesystem::path & filename)
111  {
112  std::ofstream stream;
113  stream.open(filename.c_str(), std::ios::out | std::ios::binary);
114  if (!stream.is_open())
115  mooseError(
116  "Unable to open restart file ", std::filesystem::absolute(filename), " for writing");
117  paths.push_back(filename);
118  return stream;
119  };
120 
121  // Open and write
122  auto header_stream = open(header_file);
123  auto data_stream = open(data_file);
124  write(header_stream, data_stream);
125 
126  // Update the folder's modified time to now for consistency
127  // (this used in checking for the latest checkpoint)
128  const auto data_write_time = std::filesystem::last_write_time(header_file);
129  std::filesystem::last_write_time(dir, data_write_time);
130 
131  return paths;
132 }
std::string name(const ElemQuality q)
OStreamProxy err
void write(std::ostream &header_stream, std::ostream &data_stream)
Writes the restartable data to header stream header_stream and data stream data_stream.
static const std::string & restartableDataFile()
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
static const unsigned int CURRENT_BACKUP_FILE_VERSION
The current version for the backup file.
Class for doing restart.
std::size_t dataSize() const
static const std::string & restartableHeaderFile()
Base class for MOOSE-based applications.
Definition: MooseApp.h:85
int COMPARE_HASH_CODE_TYPE
The type to used for comparing hash codes (sanity checking)
RestartableDataMap & currentData(const THREAD_ID tid)
Storage for restartable data that is ordered based on insertion order.
RestartableDataWriter(MooseApp &app, RestartableDataMap &data)
processor_id_type n_processors() const
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
IntRange< T > make_range(T beg, T end)
void dataStore(std::ostream &stream, PenetrationInfo *&pinfo, void *context)