equation_systems_io.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2014 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 #include "libmesh/libmesh_common.h"
21 
22 
23 // C++ Includes
24 #include <cstdio> // for std::sprintf
25 #include <sstream>
26 
27 // Local Includes
30 #include "libmesh/mesh_base.h"
31 #include "libmesh/mesh_tools.h"
32 #include "libmesh/parallel_mesh.h"
33 #include "libmesh/parallel.h"
34 #include "libmesh/serial_mesh.h"
35 #include "libmesh/xdr_cxx.h"
37 
38 namespace libMesh
39 {
40 
41 // Forward Declarations
42 
43 // Anonymous namespace for implementation details.
44 namespace {
45  std::string local_file_name (const unsigned int processor_id,
46  const std::string &name)
47  {
48  std::string basename(name);
49  char buf[256];
50 
51  if (basename.size() - basename.rfind(".bz2") == 4)
52  {
53  basename.erase(basename.end()-4, basename.end());
54  std::sprintf(buf, "%s.%04d.bz2", basename.c_str(), processor_id);
55  }
56  else if (basename.size() - basename.rfind(".gz") == 3)
57  {
58  basename.erase(basename.end()-3, basename.end());
59  std::sprintf(buf, "%s.%04d.gz", basename.c_str(), processor_id);
60  }
61  else
62  std::sprintf(buf, "%s.%04d", basename.c_str(), processor_id);
63 
64  return std::string(buf);
65  }
66 }
67 
68 
69 
70 
71 // ------------------------------------------------------------
72 // EquationSystem class implementation
73  template <typename InValType>
74 void EquationSystems::read (const std::string& name,
75  const unsigned int read_flags,
76  bool partition_agnostic)
77 {
79  if (name.find(".xdr") != std::string::npos)
80  mode = DECODE;
81  this->read(name, mode, read_flags, partition_agnostic);
82 
83 #ifdef LIBMESH_ENABLE_AMR
84  MeshRefinement mesh_refine(_mesh);
85  mesh_refine.clean_refinement_flags();
86 #endif
87 }
88 
89 
90 
91 template <typename InValType>
92 void EquationSystems::read (const std::string& name,
93  const libMeshEnums::XdrMODE mode,
94  const unsigned int read_flags,
95  bool partition_agnostic)
96 {
97 #ifdef LIBMESH_ENABLE_EXCEPTIONS
98 
99  // If we have exceptions enabled we can be considerate and try
100  // to read old restart files which contain infinite element
101  // information but do not have the " with infinite elements"
102  // string in the version information.
103 
104  // First try the read the user requested
105  try
106  {
107  this->_read_impl<InValType> (name, mode, read_flags, partition_agnostic);
108  }
109 
110  // If that fails, try it again but explicitly request we look for infinite element info
111  catch (...)
112  {
113  libMesh::out << "\n*********************************************************************\n"
114  << "READING THE FILE \"" << name << "\" FAILED.\n"
115  << "It is possible this file contains infinite element information,\n"
116  << "but the version string does not contain \" with infinite elements\"\n"
117  << "Let's try this again, but looking for infinite element information...\n"
118  << "*********************************************************************\n"
119  << std::endl;
120 
121  try
122  {
123  this->_read_impl<InValType> (name, mode, read_flags | EquationSystems::TRY_READ_IFEMS, partition_agnostic);
124  }
125 
126  // If all that failed, we are out of ideas here...
127  catch (...)
128  {
129  libMesh::out << "\n*********************************************************************\n"
130  << "Well, at least we tried!\n"
131  << "Good Luck!!\n"
132  << "*********************************************************************\n"
133  << std::endl;
134  throw;
135  }
136  }
137 
138 #else
139 
140  // no exceptions - cross your fingers...
141  this->_read_impl<InValType> (name, mode, read_flags, partition_agnostic);
142 
143 #endif // #ifdef LIBMESH_ENABLE_EXCEPTIONS
144 
145 #ifdef LIBMESH_ENABLE_AMR
146  MeshRefinement mesh_refine(_mesh);
147  mesh_refine.clean_refinement_flags();
148 #endif
149 }
150 
151 
152 
153  template <typename InValType>
154 void EquationSystems::_read_impl (const std::string& name,
155  const libMeshEnums::XdrMODE mode,
156  const unsigned int read_flags,
157  bool partition_agnostic)
158 {
222  // Set booleans from the read_flags argument
223  const bool read_header = read_flags & EquationSystems::READ_HEADER;
224  const bool read_data = read_flags & EquationSystems::READ_DATA;
225  const bool read_additional_data = read_flags & EquationSystems::READ_ADDITIONAL_DATA;
226  const bool read_legacy_format = read_flags & EquationSystems::READ_LEGACY_FORMAT;
227  const bool try_read_ifems = read_flags & EquationSystems::TRY_READ_IFEMS;
228  const bool read_basic_only = read_flags & EquationSystems::READ_BASIC_ONLY;
229  bool read_parallel_files = false;
230 
231  std::map<std::string, System*> xda_systems;
232 
233  // This will unzip a file with .bz2 as the extension, otherwise it
234  // simply returns the name if the file need not be unzipped.
235  Xdr io ((this->processor_id() == 0) ? name : "", mode);
236  libmesh_assert (io.reading());
237 
238  {
239  // 1.)
240  // Read the version header.
241  std::string version = "legacy";
242  if (!read_legacy_format)
243  {
244  if (this->processor_id() == 0) io.data(version);
245  this->comm().broadcast(version);
246 
247  // All processors have the version header, if it does not contain
248  // "libMesh" something then it is a legacy file.
249  std::string::size_type lm_pos = version.find("libMesh");
250  if (!(lm_pos < version.size()))
251  {
252  io.close();
253 
254  // Recursively call this read() function but with the
255  // EquationSystems::READ_LEGACY_FORMAT bit set.
256  this->read (name, mode, (read_flags | EquationSystems::READ_LEGACY_FORMAT), partition_agnostic);
257  return;
258  }
259 
260  // Figure out the libMesh version that created this file
261  std::istringstream iss(version.substr(lm_pos + 8));
262  int ver_major = 0, ver_minor = 0, ver_patch = 0;
263  char dot;
264  iss >> ver_major >> dot >> ver_minor >> dot >> ver_patch;
265  io.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch));
266 
267 
268  read_parallel_files = (version.rfind(" parallel") < version.size());
269 
270  // If requested that we try to read infinite element information,
271  // and the string " with infinite elements" is not in the version,
272  // then tack it on. This is for compatibility reading ifem
273  // files written prior to 11/10/2008 - BSK
274  if (try_read_ifems)
275  if (!(version.rfind(" with infinite elements") < version.size()))
276  version += " with infinite elements";
277 
278  }
279  else
280  libmesh_deprecated();
281 
282  START_LOG("read()","EquationSystems");
283 
284  // 2.)
285  // Read the number of equation systems
286  unsigned int n_sys=0;
287  if (this->processor_id() == 0) io.data (n_sys);
288  this->comm().broadcast(n_sys);
289 
290  for (unsigned int sys=0; sys<n_sys; sys++)
291  {
292  // 3.)
293  // Read the name of the sys-th equation system
294  std::string sys_name;
295  if (this->processor_id() == 0) io.data (sys_name);
296  this->comm().broadcast(sys_name);
297 
298  // 4.)
299  // Read the type of the sys-th equation system
300  std::string sys_type;
301  if (this->processor_id() == 0) io.data (sys_type);
302  this->comm().broadcast(sys_type);
303 
304  if (read_header)
305  this->add_system (sys_type, sys_name);
306 
307  // 5.) - 9.)
308  // Let System::read_header() do the job
309  System& new_system = this->get_system(sys_name);
310  new_system.read_header (io,
311  version,
312  read_header,
313  read_additional_data,
314  read_legacy_format);
315 
316  xda_systems.insert(std::make_pair(sys_name, &new_system));
317 
318  // If we're only creating "basic" systems, we need to tell
319  // each system that before we call init() later.
320  if (read_basic_only)
321  new_system.set_basic_system_only();
322  }
323  }
324 
325 
326 
327  // Now we are ready to initialize the underlying data
328  // structures. This will initialize the vectors for
329  // storage, the dof_map, etc...
330  if (read_header)
331  this->init();
332 
333  // 10.) & 11.)
334  // Read and set the numeric vector values
335  if (read_data)
336  {
337  // the EquationSystems::read() method should look constant from the mesh
338  // perspective, but we need to assign a temporary numbering to the nodes
339  // and elements in the mesh, which requires that we abuse const_cast
340  if (!read_legacy_format && partition_agnostic)
341  {
342  MeshBase &mesh = const_cast<MeshBase&>(this->get_mesh());
344  }
345 
346  Xdr local_io (read_parallel_files ? local_file_name(this->processor_id(),name) : "", mode);
347 
348  std::map<std::string, System*>::iterator
349  pos = xda_systems.begin();
350 
351  for (; pos != xda_systems.end(); ++pos)
352  if (read_legacy_format)
353  {
354  libmesh_deprecated();
355  pos->second->read_legacy_data (io, read_additional_data);
356  }
357  else
358  if (read_parallel_files)
359  pos->second->read_parallel_data<InValType> (local_io, read_additional_data);
360  else
361  pos->second->read_serialized_data<InValType> (io, read_additional_data);
362 
363 
364  // Undo the temporary numbering.
365  if (!read_legacy_format && partition_agnostic)
367  }
368 
369  STOP_LOG("read()","EquationSystems");
370 
371  // Localize each system's data
372  this->update();
373 }
374 
375 
376 
377 void EquationSystems::write(const std::string& name,
378  const unsigned int write_flags,
379  bool partition_agnostic) const
380 {
382  if (name.find(".xdr") != std::string::npos)
383  mode = ENCODE;
384  this->write(name, mode, write_flags, partition_agnostic);
385 }
386 
387 
388 
389 void EquationSystems::write(const std::string& name,
390  const libMeshEnums::XdrMODE mode,
391  const unsigned int write_flags,
392  bool partition_agnostic) const
393 {
457  // the EquationSystems::write() method should look constant,
458  // but we need to assign a temporary numbering to the nodes
459  // and elements in the mesh, which requires that we abuse const_cast
460  if(partition_agnostic)
461  {
462  MeshBase &mesh = const_cast<MeshBase&>(this->get_mesh());
464  }
465 
466  // set booleans from write_flags argument
467  const bool write_data = write_flags & EquationSystems::WRITE_DATA;
468  const bool write_additional_data = write_flags & EquationSystems::WRITE_ADDITIONAL_DATA;
469 
470  // always write parallel files if we're instructed to write in
471  // parallel
472  const bool write_parallel_files =
473  (write_flags & EquationSystems::WRITE_PARALLEL_FILES) ||
474  // but also write parallel files if we haven't been instructed to
475  // write in serial and we're on a distributed mesh
476  (!(write_flags & EquationSystems::WRITE_SERIAL_FILES) &&
477  !this->get_mesh().is_serial());
478 
479  // New scope so that io will close before we try to zip the file
480  {
481  Xdr io((this->processor_id()==0) ? name : "", mode);
482  libmesh_assert (io.writing());
483 
484  START_LOG("write()","EquationSystems");
485 
486  const unsigned int proc_id = this->processor_id();
487  unsigned int n_sys = this->n_systems();
488 
489  std::map<std::string, System*>::const_iterator
490  pos = _systems.begin();
491 
492  std::string comment;
493  char buf[256];
494 
495  // set the version number in the Xdr object
496  io.set_version(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION,
497  LIBMESH_MINOR_VERSION,
498  LIBMESH_MICRO_VERSION));
499 
500  // Only write the header information
501  // if we are processor 0.
502  if (proc_id == 0)
503  {
504  // 1.)
505  // Write the version header
506  std::string version("libMesh-" + libMesh::get_io_compatibility_version());
507  if (write_parallel_files) version += " parallel";
508 
509 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
510  version += " with infinite elements";
511 #endif
512  io.data (version, "# File Format Identifier");
513 
514  // 2.)
515  // Write the number of equation systems
516  io.data (n_sys, "# No. of Equation Systems");
517 
518  while (pos != _systems.end())
519  {
520  // 3.)
521  // Write the name of the sys_num-th system
522  {
523  const unsigned int sys_num = pos->second->number();
524  std::string sys_name = pos->first;
525 
526  comment = "# Name, System No. ";
527  std::sprintf(buf, "%d", sys_num);
528  comment += buf;
529 
530  io.data (sys_name, comment.c_str());
531  }
532 
533  // 4.)
534  // Write the type of system handled
535  {
536  const unsigned int sys_num = pos->second->number();
537  std::string sys_type = pos->second->system_type();
538 
539  comment = "# Type, System No. ";
540  std::sprintf(buf, "%d", sys_num);
541  comment += buf;
542 
543  io.data (sys_type, comment.c_str());
544  }
545 
546  // 5.) - 9.)
547  // Let System::write_header() do the job
548  pos->second->write_header (io, version, write_additional_data);
549 
550  ++pos;
551  }
552  }
553 
554  // Start from the first system, again,
555  // to write vectors to disk, if wanted
556  if (write_data)
557  {
558  // open a parallel buffer if warranted.
559  Xdr local_io (write_parallel_files ? local_file_name(this->processor_id(),name) : "", mode);
560 
561  for (pos = _systems.begin(); pos != _systems.end(); ++pos)
562  {
563  // 10.) + 11.)
564  if (write_parallel_files)
565  pos->second->write_parallel_data (local_io,write_additional_data);
566  else
567  pos->second->write_serialized_data (io,write_additional_data);
568  }
569  }
570 
571  STOP_LOG("write()","EquationSystems");
572  }
573 
574  // the EquationSystems::write() method should look constant,
575  // but we need to undo the temporary numbering of the nodes
576  // and elements in the mesh, which requires that we abuse const_cast
577  if(partition_agnostic)
578  const_cast<MeshBase&>(_mesh).fix_broken_node_and_element_numbering();
579 }
580 
581 
582 
583 // template specialization
584 
585 template void EquationSystems::read<Number> (const std::string& name, const unsigned int read_flags, bool partition_agnostic);
586 template void EquationSystems::read<Number> (const std::string& name, const libMeshEnums::XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
587 template void EquationSystems::_read_impl<Number> (const std::string& name, const libMeshEnums::XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
588 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
589 template void EquationSystems::read<Real> (const std::string& name, const unsigned int read_flags, bool partition_agnostic);
590 template void EquationSystems::read<Real> (const std::string& name, const libMeshEnums::XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
591 template void EquationSystems::_read_impl<Real> (const std::string& name, const libMeshEnums::XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
592 #endif
593 
594 } // namespace libMesh

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:04 UTC

Hosted By:
SourceForge.net Logo