Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : #ifndef LIBMESH_CHECKPOINT_IO_H
21 : #define LIBMESH_CHECKPOINT_IO_H
22 :
23 :
24 : // Local includes
25 : #include "libmesh/compare_elems_by_level.h"
26 : #include "libmesh/mesh_input.h"
27 : #include "libmesh/mesh_output.h"
28 : #include "libmesh/mesh_communication.h"
29 : #include "libmesh/parallel_object.h"
30 :
31 : // C++ includes
32 : #include <string>
33 : #include <vector>
34 :
35 : namespace libMesh
36 : {
37 : // Forward declarations
38 : class Xdr;
39 : class CheckpointIO;
40 :
41 : /**
42 : * split_mesh takes the given initialized/opened mesh and partitions it into nsplits pieces or
43 : * chunks. It returns a CheckpointIO object that can be used to write the mesh chunks into
44 : * individual files (e.g. by calling checkpoint_obj.write(out_file_name)) - the number of files is
45 : * equal to the number of chunks. This function supports MPI parallelism and can be used with
46 : * several MPI procs to speed up splitting.
47 : */
48 : std::unique_ptr<CheckpointIO> split_mesh(MeshBase & mesh, processor_id_type nsplits);
49 :
50 : /**
51 : * The CheckpointIO class can be used to write simplified restart
52 : * files that can be used to restart simulations that have
53 : * crashed.
54 : *
55 : * \author Benjamin Kirk
56 : * \author John Peterson
57 : * \author Derek Gaston
58 : * \author Roy Stogner
59 : * \date 2017
60 : */
61 116 : class CheckpointIO : public MeshInput<MeshBase>,
62 : public MeshOutput<MeshBase>,
63 : public ParallelObject
64 : {
65 : public:
66 : // The size used for encoding all id types in this file
67 : typedef largest_id_type xdr_id_type;
68 :
69 : // The size type used to read header sizes (meta data information)
70 : typedef uint64_t header_id_type;
71 :
72 : /**
73 : * Constructor. Takes a writable reference to a mesh object.
74 : * This is the constructor required to read a mesh.
75 : * The optional parameter \p binary can be used to switch
76 : * between ASCII (\p false, the default) or binary (\p true)
77 : * files.
78 : */
79 : explicit
80 : CheckpointIO (MeshBase &, const bool=false);
81 :
82 : /**
83 : * Constructor. Takes a reference to a constant mesh object.
84 : * This constructor will only allow us to write the mesh.
85 : * The optional parameter \p binary can be used to switch
86 : * between ASCII (\p false, the default) or binary (\p true)
87 : * files.
88 : */
89 : explicit
90 : CheckpointIO (const MeshBase &, const bool=false);
91 :
92 : /**
93 : * Destructor.
94 : */
95 : virtual ~CheckpointIO ();
96 :
97 : /**
98 : * This method implements reading a mesh from a specified file. If the mesh has been split for
99 : * running on several processors, input_name should simply be the name of the mesh split
100 : * directory without the "-split[n]" suffix. The number of splits will be determined
101 : * automatically by the number of processes being used for the mesh at the time of reading.
102 : */
103 : virtual void read (const std::string & input_name) override;
104 :
105 : /**
106 : * This method implements writing a mesh to a specified file. If the mesh has been split
107 : * for running on several processors, this will create a subdirectory named
108 : * "[name]-split[n]" where name is the given name argument and n is the number of
109 : * processors the mesh is split for running on. For example:
110 : *
111 : * unsigned int n_splits = 42;
112 : * std::unique_ptr<CheckpointIO> cp = split_mesh(my_mesh, n_splits);
113 : * // ...
114 : * cp->write("foo.cpr");
115 : *
116 : * would create a directory named "foo.cpr-split42".
117 : */
118 : virtual void write (const std::string & name) override;
119 :
120 : /**
121 : * Used to remove a checkpoint directory and its corresponding files. This effectively undoes
122 : * all the work done be calls to write(...). For example, if a checkpoint configuration was
123 : * written via:
124 : *
125 : * unsigned int n_splits = 42;
126 : * std::unique_ptr<CheckpointIO> cp = split_mesh(my_mesh, n_splits);
127 : * // ...
128 : * cp->write("foo.cpr");
129 : *
130 : * then you could remove all the corresponding created files/dirs by:
131 : *
132 : * CheckpointIO::cleanup(my_mesh, n_splits);
133 : *
134 : * Or for cases where the split configuration was determined automatically (e.g. via number of
135 : * running procs with distributed/parallel mesh), then you could:
136 : *
137 : * CheckpointIO::cleanup(your_mesh, your_mesh.comm().size());
138 : *
139 : * Other remaining checkpoint split configurations for the mesh are left unmodified.
140 : */
141 : static void cleanup(const std::string & input_name, processor_id_type n_procs);
142 :
143 : /**
144 : * Get/Set the flag indicating if we should read/write binary.
145 : */
146 : bool binary() const { return _binary; }
147 0 : bool & binary() { return _binary; }
148 :
149 : /**
150 : * Get/Set the flag indicating if we should read/write binary.
151 : */
152 : bool parallel() const { return _parallel; }
153 0 : bool & parallel() { return _parallel; }
154 :
155 : /**
156 : * Get/Set the version string.
157 : */
158 5080 : const std::string & version () const { return _version; }
159 1140 : std::string & version () { return _version; }
160 :
161 : /**
162 : * \returns \p true if the current file has an XDR/XDA version that
163 : * matches or exceeds 1.5
164 : *
165 : * As of this version we encode any extra integer data that has been
166 : * attached to a mesh.
167 : */
168 : bool version_at_least_1_5() const;
169 :
170 : /**
171 : * \returns \p true if the current file has an XDR/XDA version that
172 : * matches or exceeds 1.6
173 : *
174 : * As of this version we encode runtime element topology.
175 : */
176 : bool version_at_least_1_6() const;
177 :
178 : /**
179 : * \returns \p true if the current file has an XDR/XDA version that
180 : * matches or exceeds 1.7
181 : *
182 : * As of this version we encode disjoint neighbor boundary pairs.
183 : */
184 : bool version_at_least_1_7() const;
185 :
186 : /**
187 : * Get/Set the processor id or processor ids to use.
188 : *
189 : * The default processor_id to use is the processor_id() of the
190 : * mesh.
191 : *
192 : * This is used for m->n parallel checkpoint file writing:
193 : * You can force CheckpointIO to write out different partitions of a
194 : * mesh by setting which partitions to write from each processor here.
195 : */
196 : const std::vector<processor_id_type> & current_processor_ids() const { return _my_processor_ids; }
197 0 : std::vector<processor_id_type> & current_processor_ids() { return _my_processor_ids; }
198 :
199 : /**
200 : * Get/Set the n_processors to use
201 : *
202 : * The default n_processors to use is the n_processors() of the
203 : * mesh.
204 : *
205 : * This is used for m->n parallel checkpoint file writing:
206 : * You can force CheckpointIO to view the world as if it contains this number of
207 : * processors by setting it here
208 : */
209 : const processor_id_type & current_n_processors() const { return _my_n_processors; }
210 0 : processor_id_type & current_n_processors() { return _my_n_processors; }
211 :
212 : private:
213 : //---------------------------------------------------------------------------
214 : // Write Implementation
215 :
216 : /**
217 : * Write subdomain name information
218 : */
219 : void write_subdomain_names(Xdr & io) const;
220 :
221 : /**
222 : * Write the connectivity for part of a mesh
223 : */
224 : void write_connectivity (Xdr & io,
225 : const std::set<const Elem *, CompareElemIdsByLevel> & elements) const;
226 :
227 : /**
228 : * Write the remote_elem neighbor and child links for part of a mesh
229 : */
230 : void write_remote_elem (Xdr & io,
231 : const std::set<const Elem *, CompareElemIdsByLevel> & elements) const;
232 :
233 : /**
234 : * Write the nodal locations for part of a mesh
235 : */
236 : void write_nodes (Xdr & io,
237 : const connected_node_set_type & nodeset) const;
238 :
239 : /**
240 : * Write the side boundary conditions for part of a mesh
241 : */
242 : void write_bcs (Xdr & io,
243 : const std::set<const Elem *, CompareElemIdsByLevel> & elements,
244 : const std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> & bc_triples) const;
245 :
246 : /**
247 : * Write the nodal boundary conditions for part of a mesh
248 : */
249 : void write_nodesets (Xdr & io,
250 : const connected_node_set_type & nodeset,
251 : const std::vector<std::tuple<dof_id_type, boundary_id_type>> & bc_tuples) const;
252 :
253 : /**
254 : * Write boundary names information (sideset and nodeset)
255 : */
256 : void write_bc_names (Xdr & io, const BoundaryInfo & info, bool is_sideset) const;
257 :
258 : /**
259 : * Write disjoint neighbor boundary pairs
260 : */
261 : void write_disjoint_neighbor_boundary_pairs (Xdr & io) const;
262 :
263 :
264 : //---------------------------------------------------------------------------
265 : // Read Implementation
266 :
267 : /**
268 : * Read header data on processor 0, then broadcast. Returns the
269 : * number of processors for which parallel non-header files have
270 : * been written, or 0 if files were written in serial.
271 : */
272 : template <typename file_id_type>
273 : file_id_type read_header(const std::string & name);
274 :
275 : /**
276 : * Read a non-header file
277 : */
278 : template <typename file_id_type>
279 : void read_subfile(Xdr & io, bool expect_all_remote);
280 :
281 : /**
282 : * Read subdomain name information
283 : */
284 : template <typename file_id_type>
285 : void read_subdomain_names(Xdr & io);
286 :
287 : /**
288 : * Read the connectivity for a parallel, distributed mesh
289 : */
290 : template <typename file_id_type>
291 : void read_connectivity (Xdr & io);
292 :
293 : /**
294 : * Read the remote_elem neighbor and child links for a parallel, distributed mesh
295 : *
296 : * If we expect all these remote_elem links to truly be remote,
297 : * because we aren't doing an N -> M restart with M < N, then we set
298 : * \p expect_all_remote to true and test more assertions.
299 : */
300 : template <typename file_id_type>
301 : void read_remote_elem (Xdr & io, bool expect_all_remote);
302 :
303 : /**
304 : * Read the nodal locations for a parallel, distributed mesh
305 : */
306 : template <typename file_id_type>
307 : void read_nodes (Xdr & io);
308 :
309 : /**
310 : * Read the boundary conditions for a parallel, distributed mesh
311 : */
312 : template <typename file_id_type>
313 : void read_bcs (Xdr & io);
314 :
315 : /**
316 : * Read the nodeset conditions for a parallel, distributed mesh
317 : */
318 : template <typename file_id_type>
319 : void read_nodesets (Xdr & io);
320 :
321 : /**
322 : * Read boundary names information (sideset and nodeset)
323 : */
324 : template <typename file_id_type>
325 : void read_bc_names(Xdr & io, BoundaryInfo & info, bool is_sideset);
326 :
327 : /**
328 : * Read disjoint neighbor boundary pairs: the two boundary ids of
329 : * each pair, and the LIBMESH_DIM translation components of each
330 : * pair
331 : */
332 : template <typename file_id_type>
333 : void read_disjoint_neighbor_boundary_pairs
334 : (Xdr & io,
335 : std::vector<file_id_type> & pair_ids,
336 : std::vector<Real> & translations);
337 :
338 : /**
339 : * Read extra integers names information
340 : */
341 : template <typename file_id_type>
342 : void read_integers_names
343 : (Xdr & io,
344 : std::vector<std::string> & node_integer_names,
345 : std::vector<std::string> & elem_integer_names);
346 :
347 : /**
348 : * \returns The number of levels of refinement in the active mesh on
349 : * this processor.
350 : *
351 : * \note This includes _all_ elements on this processor even those
352 : * not owned by this processor! Implemented by looping over all the
353 : * active elements and finding the maximum level.
354 : */
355 : unsigned int n_active_levels_in(MeshBase::const_element_iterator begin,
356 : MeshBase::const_element_iterator end) const;
357 :
358 : processor_id_type select_split_config(const std::string & input_name, header_id_type & data_size);
359 :
360 : bool _binary;
361 : bool _parallel;
362 : std::string _version;
363 :
364 : // The processor ids to write
365 : std::vector<processor_id_type> _my_processor_ids;
366 :
367 : // The largest processor id to write
368 : processor_id_type _my_n_processors;
369 : };
370 :
371 :
372 : } // namespace libMesh
373 :
374 : #endif // LIBMESH_CHECKPOINT_IO_H
|