Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 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_XDR_IO_H
21 : #define LIBMESH_XDR_IO_H
22 :
23 :
24 : // Local includes
25 : #include "libmesh/libmesh.h"
26 : #include "libmesh/mesh_input.h"
27 : #include "libmesh/mesh_output.h"
28 : #include "libmesh/parallel_object.h"
29 :
30 : // C++ includes
31 : #include <string>
32 : #include <vector>
33 :
34 : namespace libMesh
35 : {
36 :
37 : // Forward declarations
38 : class Xdr;
39 : class Elem;
40 :
41 : /**
42 : * MeshIO class used for writing XDR (eXternal Data Representation)
43 : * and XDA mesh files. XDR/XDA is libmesh's internal data format, and
44 : * allows the full refinement tree structure of the mesh to be written
45 : * to file.
46 : *
47 : * \author Benjamin Kirk
48 : * \author John Peterson
49 : * \date 2004
50 : */
51 312 : class XdrIO : public MeshInput<MeshBase>,
52 : public MeshOutput<MeshBase>,
53 : public ParallelObject
54 : {
55 : public:
56 : // The size used for encoding all id types in this file
57 : typedef largest_id_type xdr_id_type;
58 :
59 : // The size type used to read pre-1.3.0 header sizes (meta data information)
60 : typedef uint32_t old_header_id_type;
61 :
62 : // Likewise, but for 1.3.0 and newer header files
63 : typedef uint64_t new_header_id_type;
64 :
65 : /**
66 : * Constructor. Takes a writable reference to a mesh object.
67 : * This is the constructor required to read a mesh.
68 : * The optional parameter \p binary can be used to switch
69 : * between ASCII (\p false, the default) or binary (\p true)
70 : * files.
71 : */
72 : explicit
73 : XdrIO (MeshBase &, const bool=false);
74 :
75 : /**
76 : * Constructor. Takes a reference to a constant mesh object.
77 : * This constructor will only allow us to write the mesh.
78 : * The optional parameter \p binary can be used to switch
79 : * between ASCII (\p false, the default) or binary (\p true)
80 : * files.
81 : */
82 : explicit
83 : XdrIO (const MeshBase &, const bool=false);
84 :
85 : /**
86 : * Destructor.
87 : */
88 : virtual ~XdrIO ();
89 :
90 : /**
91 : * This method implements reading a mesh from a specified file.
92 : */
93 : virtual void read (const std::string &) override;
94 :
95 : /**
96 : * This method implements writing a mesh to a specified file.
97 : */
98 : virtual void write (const std::string &) override;
99 :
100 : /**
101 : * Get/Set the flag indicating if we should read/write binary.
102 : */
103 : bool binary() const { return _binary; }
104 270 : bool & binary() { return _binary; }
105 :
106 : /**
107 : * Get/Set the flag indicating if we should read/write legacy.
108 : */
109 : bool legacy() const { return _legacy; }
110 384 : bool & legacy() { return _legacy; }
111 :
112 : /**
113 : * Report whether we should write parallel files.
114 : */
115 : bool write_parallel() const;
116 :
117 : /**
118 : * Insist that we should/shouldn't write parallel files.
119 : */
120 : void set_write_parallel (bool do_parallel = true);
121 :
122 : /**
123 : * Insist that we should write parallel files if and only if the
124 : * mesh is an already distributed DistributedMesh.
125 : */
126 : void set_auto_parallel ();
127 :
128 : /**
129 : * Get/Set the version string. Valid version strings:
130 : *
131 : * \verbatim
132 : * "libMesh-0.7.0+"
133 : * "libMesh-0.7.0+ parallel"
134 : * \endverbatim
135 : *
136 : * If "libMesh" is not detected in the version string the
137 : * \p LegacyXdrIO class will be used to read older
138 : * (pre version 0.7.0) mesh files.
139 : */
140 62122 : const std::string & version () const { return _version; }
141 4586 : std::string & version () { return _version; }
142 :
143 : /**
144 : * Get/Set the boundary condition file name.
145 : */
146 : const std::string & boundary_condition_file_name() const { return _bc_file_name; }
147 15204 : std::string & boundary_condition_file_name() { return _bc_file_name; }
148 :
149 : /**
150 : * Get/Set the partitioning file name.
151 : */
152 1425 : const std::string & partition_map_file_name() const { return _partition_map_file; }
153 7891 : std::string & partition_map_file_name() { return _partition_map_file; }
154 :
155 : /**
156 : * Get/Set the subdomain file name.
157 : */
158 1425 : const std::string & subdomain_map_file_name() const { return _subdomain_map_file; }
159 9358 : std::string & subdomain_map_file_name() { return _subdomain_map_file; }
160 :
161 : /**
162 : * Get/Set the polynomial degree file name.
163 : */
164 1425 : const std::string & polynomial_level_file_name() const { return _p_level_file; }
165 7891 : std::string & polynomial_level_file_name() { return _p_level_file; }
166 :
167 : /**
168 : * \returns \p true if the current file has an XDR/XDA version that
169 : * matches or exceeds 0.9.2.
170 : *
171 : * As of this version we encode integer field widths, nodesets,
172 : * subdomain names, boundary names, and element unique_id values (if
173 : * they exist) into our files.
174 : */
175 : bool version_at_least_0_9_2() const;
176 :
177 : /**
178 : * \returns \p true if the current file has an XDR/XDA version that
179 : * matches or exceeds 0.9.6.
180 : *
181 : * In this version we add node unique_id values to our files, if
182 : * they exist.
183 : */
184 : bool version_at_least_0_9_6() const;
185 :
186 : /**
187 : * \returns \p true if the current file has an XDR/XDA version that
188 : * matches or exceeds 1.1.0.
189 : *
190 : * In this version we add edge and shellface boundary conditions to
191 : * our files.
192 : */
193 : bool version_at_least_1_1_0() const;
194 :
195 : /**
196 : * \returns \p true if the current file has an XDR/XDA version that
197 : * matches or exceeds 1.3.0.
198 : *
199 : * In this version we fix handling of uint64_t binary values on
200 : * Linux, which were previously miswritten as 32 bit via xdr_long.
201 : */
202 : bool version_at_least_1_3_0() const;
203 :
204 : /**
205 : * \returns \p true if the current file has an XDR/XDA version that
206 : * matches or exceeds 1.8.0.
207 : *
208 : * In this version we added support for writing the Mesh's "extra"
209 : * integer fields to the file.
210 : */
211 : bool version_at_least_1_8_0() const;
212 :
213 : private:
214 :
215 :
216 : //---------------------------------------------------------------------------
217 : // Write Implementation
218 : /**
219 : * Write subdomain name information - NEW in 0.9.2 format
220 : */
221 : void write_serialized_subdomain_names(Xdr & io) const;
222 :
223 : /**
224 : * Write the connectivity for a parallel, distributed mesh
225 : */
226 : void write_serialized_connectivity (Xdr & io, const dof_id_type n_elem,
227 : const new_header_id_type n_elem_integers) const;
228 :
229 : /**
230 : * Write the nodal locations for a parallel, distributed mesh
231 : */
232 : void write_serialized_nodes (Xdr & io, const dof_id_type n_nodes,
233 : const new_header_id_type n_node_integers) const;
234 :
235 : /**
236 : * Helper function used in write_serialized_side_bcs, write_serialized_edge_bcs, and
237 : * write_serialized_shellface_bcs.
238 : */
239 : void write_serialized_bcs_helper (Xdr & io, const new_header_id_type n_side_bcs, const std::string bc_type) const;
240 :
241 : /**
242 : * Write the side boundary conditions for a parallel, distributed mesh
243 : */
244 : void write_serialized_side_bcs (Xdr & io, const new_header_id_type n_side_bcs) const;
245 :
246 : /**
247 : * Write the edge boundary conditions for a parallel, distributed mesh.
248 : * NEW in 1.1.0 format.
249 : */
250 : void write_serialized_edge_bcs (Xdr & io, const new_header_id_type n_edge_bcs) const;
251 :
252 : /**
253 : * Write the "shell face" boundary conditions for a parallel, distributed mesh.
254 : * NEW in 1.1.0 format.
255 : */
256 : void write_serialized_shellface_bcs (Xdr & io, const new_header_id_type n_shellface_bcs) const;
257 :
258 : /**
259 : * Write the boundary conditions for a parallel, distributed mesh
260 : */
261 : void write_serialized_nodesets (Xdr & io, const new_header_id_type n_nodesets) const;
262 :
263 : /**
264 : * Write boundary names information (sideset and nodeset) - NEW in 0.9.2 format
265 : */
266 : void write_serialized_bc_names (Xdr & io, const BoundaryInfo & info, bool is_sideset) const;
267 :
268 :
269 : //---------------------------------------------------------------------------
270 : // Read Implementation
271 : //
272 : // In the function templates below, the "T type_size" argument is only
273 : // used for template argument deduction purposes. The value of this
274 : // parameter can be arbitrary because it will not be used within the
275 : // function.
276 :
277 : /**
278 : * Read header information - templated to handle old (4-byte) or new
279 : * (8-byte) header id types.
280 : */
281 : template <typename T>
282 : void read_header(Xdr & io, std::vector<T> & meta_data);
283 :
284 : /**
285 : * Read subdomain name information - NEW in 0.9.2 format
286 : */
287 : void read_serialized_subdomain_names(Xdr & io);
288 :
289 : /**
290 : * Read the connectivity for a parallel, distributed mesh.
291 : */
292 : template <typename T>
293 : void read_serialized_connectivity (Xdr & io,
294 : const dof_id_type n_elem,
295 : const std::vector<new_header_id_type> & meta_data,
296 : T type_size);
297 :
298 : /**
299 : * Read the nodal locations for a parallel, distributed mesh
300 : */
301 : void read_serialized_nodes (Xdr & io, const dof_id_type n_nodes,
302 : const std::vector<new_header_id_type> & meta_data);
303 :
304 : /**
305 : * Helper function used in read_serialized_side_bcs, read_serialized_edge_bcs, and
306 : * read_serialized_shellface_bcs.
307 : */
308 : template <typename T>
309 : void read_serialized_bcs_helper (Xdr & io, T type_size, const std::string bc_type);
310 :
311 : /**
312 : * Read the side boundary conditions for a parallel, distributed mesh
313 : * \returns The number of bcs read
314 : */
315 : template <typename T>
316 : void read_serialized_side_bcs (Xdr & io, T type_size);
317 :
318 : /**
319 : * Read the edge boundary conditions for a parallel, distributed mesh.
320 : * NEW in 1.1.0 format.
321 : * \returns The number of bcs read
322 : */
323 : template <typename T>
324 : void read_serialized_edge_bcs (Xdr & io, T type_size);
325 :
326 : /**
327 : * Read the "shell face" boundary conditions for a parallel, distributed mesh.
328 : * NEW in 1.1.0 format.
329 : * \returns The number of bcs read
330 : */
331 : template <typename T>
332 : void read_serialized_shellface_bcs (Xdr & io, T type_size);
333 :
334 : /**
335 : * Read the nodeset conditions for a parallel, distributed mesh
336 : * \returns The number of nodesets read
337 : */
338 : template <typename T>
339 : void read_serialized_nodesets (Xdr & io, T type_size);
340 :
341 : /**
342 : * Read boundary names information (sideset and nodeset) - NEW in 0.9.2 format
343 : */
344 : void read_serialized_bc_names(Xdr & io, BoundaryInfo & info, bool is_sideset);
345 :
346 : //-------------------------------------------------------------------------
347 : /**
348 : * Pack an element into a transfer buffer for parallel communication.
349 : */
350 : void pack_element (std::vector<xdr_id_type> & conn,
351 : const Elem * elem,
352 : const dof_id_type parent_id,
353 : const dof_id_type parent_pid,
354 : const new_header_id_type n_elem_integers) const;
355 :
356 : bool _binary;
357 : bool _legacy;
358 : bool _write_serial;
359 : bool _write_parallel;
360 : bool _write_unique_id;
361 : unsigned int _field_width;
362 : std::string _version;
363 : std::string _bc_file_name;
364 : std::string _partition_map_file;
365 : std::string _subdomain_map_file;
366 : std::string _p_level_file;
367 :
368 : /**
369 : * Define the block size to use for chunked IO.
370 : */
371 : static const std::size_t io_blksize;
372 : };
373 :
374 :
375 : // ------------------------------------------------------------
376 : // XdrIO inline members
377 :
378 : inline
379 1383 : bool XdrIO::write_parallel() const
380 : {
381 : // We can't insist on both serial and parallel
382 42 : libmesh_assert (!this->_write_serial || !this->_write_parallel);
383 :
384 : // If we insisted on serial, do that
385 1425 : if (this->_write_serial)
386 0 : return false;
387 :
388 : // If we insisted on parallel, do that
389 1425 : if (this->_write_parallel)
390 0 : return true;
391 :
392 : // If we're doing things automatically, check the mesh
393 84 : const MeshBase & mesh = MeshOutput<MeshBase>::mesh();
394 1425 : return !mesh.is_serial();
395 : }
396 :
397 :
398 :
399 : inline
400 : void XdrIO::set_write_parallel (bool do_parallel)
401 : {
402 : this->_write_parallel = do_parallel;
403 :
404 : this->_write_serial = !do_parallel;
405 : }
406 :
407 :
408 :
409 : inline
410 : void XdrIO::set_auto_parallel ()
411 : {
412 : this->_write_serial = false;
413 : this->_write_parallel = false;
414 : }
415 :
416 :
417 : } // namespace libMesh
418 :
419 :
420 :
421 : #endif // LIBMESH_XDR_IO_H
|