equation_systems_io.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 #include "libmesh/libmesh_common.h" 00020 #include "libmesh/libmesh_logging.h" 00021 00022 00023 // C++ Includes 00024 #include <cstdio> // for std::sprintf 00025 #include <sstream> 00026 00027 // Local Includes 00028 #include "libmesh/libmesh_version.h" 00029 #include "libmesh/equation_systems.h" 00030 #include "libmesh/mesh_base.h" 00031 #include "libmesh/mesh_tools.h" 00032 #include "libmesh/parallel_mesh.h" 00033 #include "libmesh/parallel.h" 00034 #include "libmesh/serial_mesh.h" 00035 #include "libmesh/xdr_cxx.h" 00036 #include "libmesh/mesh_refinement.h" 00037 00038 namespace libMesh 00039 { 00040 00041 // Forward Declarations 00042 00043 // Anonymous namespace for implementation details. 00044 namespace { 00045 std::string local_file_name (const std::string &name) 00046 { 00047 std::string basename(name); 00048 char buf[256]; 00049 00050 if (basename.size() - basename.rfind(".bz2") == 4) 00051 { 00052 basename.erase(basename.end()-4, basename.end()); 00053 std::sprintf(buf, "%s.%04d.bz2", basename.c_str(), libMesh::processor_id()); 00054 } 00055 else if (basename.size() - basename.rfind(".gz") == 3) 00056 { 00057 basename.erase(basename.end()-3, basename.end()); 00058 std::sprintf(buf, "%s.%04d.gz", basename.c_str(), libMesh::processor_id()); 00059 } 00060 else 00061 std::sprintf(buf, "%s.%04d", basename.c_str(), libMesh::processor_id()); 00062 00063 return std::string(buf); 00064 } 00065 } 00066 00067 00068 00069 00070 // ------------------------------------------------------------ 00071 // EquationSystem class implementation 00072 void EquationSystems::read (const std::string& name, 00073 const unsigned int read_flags) 00074 { 00075 libMeshEnums::XdrMODE mode = READ; 00076 if (name.find(".xdr") != std::string::npos) 00077 mode = DECODE; 00078 this->read(name, mode, read_flags); 00079 00080 #ifdef LIBMESH_ENABLE_AMR 00081 MeshRefinement mesh_refine(_mesh); 00082 mesh_refine.clean_refinement_flags(); 00083 #endif 00084 } 00085 00086 00087 00088 void EquationSystems::read (const std::string& name, 00089 const libMeshEnums::XdrMODE mode, 00090 const unsigned int read_flags) 00091 { 00092 #ifdef LIBMESH_ENABLE_EXCEPTIONS 00093 00094 // If we have exceptions enabled we can be considerate and try 00095 // to read old restart files which contain infinite element 00096 // information but do not have the " with infinite elements" 00097 // string in the version information. 00098 00099 // First try the read the user requested 00100 try 00101 { 00102 this->_read_impl (name, mode, read_flags); 00103 } 00104 00105 // If that fails, try it again but explicitly request we look for infinite element info 00106 catch (...) 00107 { 00108 libMesh::out << "\n*********************************************************************\n" 00109 << "READING THE FILE \"" << name << "\" FAILED.\n" 00110 << "It is possible this file contains infinite element information,\n" 00111 << "but the version string does not contain \" with infinite elements\"\n" 00112 << "Let's try this again, but looking for infinite element information...\n" 00113 << "*********************************************************************\n" 00114 << std::endl; 00115 00116 try 00117 { 00118 this->_read_impl (name, mode, read_flags | EquationSystems::TRY_READ_IFEMS); 00119 } 00120 00121 // If all that failed, we are out of ideas here... 00122 catch (...) 00123 { 00124 libMesh::out << "\n*********************************************************************\n" 00125 << "Well, at least we tried!\n" 00126 << "Good Luck!!\n" 00127 << "*********************************************************************\n" 00128 << std::endl; 00129 throw; 00130 } 00131 } 00132 00133 #else 00134 00135 // no exceptions - cross your fingers... 00136 this->_read_impl (name, mode, read_flags); 00137 00138 #endif // #ifdef LIBMESH_ENABLE_EXCEPTIONS 00139 00140 #ifdef LIBMESH_ENABLE_AMR 00141 MeshRefinement mesh_refine(_mesh); 00142 mesh_refine.clean_refinement_flags(); 00143 #endif 00144 } 00145 00146 00147 00148 void EquationSystems::_read_impl (const std::string& name, 00149 const libMeshEnums::XdrMODE mode, 00150 const unsigned int read_flags) 00151 { 00215 // Set booleans from the read_flags argument 00216 const bool read_header = read_flags & EquationSystems::READ_HEADER; 00217 const bool read_data = read_flags & EquationSystems::READ_DATA; 00218 const bool read_additional_data = read_flags & EquationSystems::READ_ADDITIONAL_DATA; 00219 const bool read_legacy_format = read_flags & EquationSystems::READ_LEGACY_FORMAT; 00220 const bool try_read_ifems = read_flags & EquationSystems::TRY_READ_IFEMS; 00221 const bool read_basic_only = read_flags & EquationSystems::READ_BASIC_ONLY; 00222 bool read_parallel_files = false; 00223 00224 std::map<std::string, System*> xda_systems; 00225 00226 // This will unzip a file with .bz2 as the extension, otherwise it 00227 // simply returns the name if the file need not be unzipped. 00228 Xdr io ((libMesh::processor_id() == 0) ? name : "", mode); 00229 libmesh_assert (io.reading()); 00230 00231 { 00232 // 1.) 00233 // Read the version header. 00234 std::string version = "legacy"; 00235 if (!read_legacy_format) 00236 { 00237 if (libMesh::processor_id() == 0) io.data(version); 00238 CommWorld.broadcast(version); 00239 00240 // All processors have the version header, if it does not contain 00241 // "libMesh" something then it is a legacy file. 00242 std::string::size_type lm_pos = version.find("libMesh"); 00243 if (!(lm_pos < version.size())) 00244 { 00245 io.close(); 00246 00247 // Recursively call this read() function but with the 00248 // EquationSystems::READ_LEGACY_FORMAT bit set. 00249 this->read (name, mode, (read_flags | EquationSystems::READ_LEGACY_FORMAT)); 00250 return; 00251 } 00252 00253 // Figure out the libMesh version that created this file 00254 std::istringstream iss(version.substr(lm_pos + 8)); 00255 int ver_major = 0, ver_minor = 0, ver_patch = 0; 00256 char dot; 00257 iss >> ver_major >> dot >> ver_minor >> dot >> ver_patch; 00258 io.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch)); 00259 00260 00261 read_parallel_files = (version.rfind(" parallel") < version.size()); 00262 00263 // If requested that we try to read infinite element information, 00264 // and the string " with infinite elements" is not in the version, 00265 // then tack it on. This is for compatibility reading ifem 00266 // files written prior to 11/10/2008 - BSK 00267 if (try_read_ifems) 00268 if (!(version.rfind(" with infinite elements") < version.size())) 00269 version += " with infinite elements"; 00270 00271 } 00272 else 00273 libmesh_deprecated(); 00274 00275 START_LOG("read()","EquationSystems"); 00276 00277 // 2.) 00278 // Read the number of equation systems 00279 unsigned int n_sys=0; 00280 if (libMesh::processor_id() == 0) io.data (n_sys); 00281 CommWorld.broadcast(n_sys); 00282 00283 for (unsigned int sys=0; sys<n_sys; sys++) 00284 { 00285 // 3.) 00286 // Read the name of the sys-th equation system 00287 std::string sys_name; 00288 if (libMesh::processor_id() == 0) io.data (sys_name); 00289 CommWorld.broadcast(sys_name); 00290 00291 // 4.) 00292 // Read the type of the sys-th equation system 00293 std::string sys_type; 00294 if (libMesh::processor_id() == 0) io.data (sys_type); 00295 CommWorld.broadcast(sys_type); 00296 00297 if (read_header) 00298 this->add_system (sys_type, sys_name); 00299 00300 // 5.) - 9.) 00301 // Let System::read_header() do the job 00302 System& new_system = this->get_system(sys_name); 00303 new_system.read_header (io, 00304 version, 00305 read_header, 00306 read_additional_data, 00307 read_legacy_format); 00308 00309 xda_systems.insert(std::make_pair(sys_name, &new_system)); 00310 00311 // If we're only creating "basic" systems, we need to tell 00312 // each system that before we call init() later. 00313 if (read_basic_only) 00314 new_system.set_basic_system_only(); 00315 } 00316 } 00317 00318 00319 00320 // Now we are ready to initialize the underlying data 00321 // structures. This will initialize the vectors for 00322 // storage, the dof_map, etc... 00323 if (read_header) 00324 this->init(); 00325 00326 // 10.) & 11.) 00327 // Read and set the numeric vector values 00328 if (read_data) 00329 { 00330 // the EquationSystems::read() method should look constant from the mesh 00331 // perspective, but we need to assign a temporary numbering to the nodes 00332 // and elements in the mesh, which requires that we abuse const_cast 00333 if (!read_legacy_format) 00334 { 00335 MeshBase &mesh = const_cast<MeshBase&>(this->get_mesh()); 00336 MeshTools::Private::globally_renumber_nodes_and_elements(mesh); 00337 } 00338 00339 Xdr local_io (read_parallel_files ? local_file_name(name) : "", mode); 00340 00341 std::map<std::string, System*>::iterator 00342 pos = xda_systems.begin(); 00343 00344 for (; pos != xda_systems.end(); ++pos) 00345 if (read_legacy_format) 00346 { 00347 libmesh_deprecated(); 00348 pos->second->read_legacy_data (io, read_additional_data); 00349 } 00350 else 00351 if (read_parallel_files) 00352 pos->second->read_parallel_data (local_io, read_additional_data); 00353 else 00354 pos->second->read_serialized_data (io, read_additional_data); 00355 00356 00357 // Undo the temporary numbering. 00358 if (!read_legacy_format) 00359 _mesh.fix_broken_node_and_element_numbering(); 00360 } 00361 00362 STOP_LOG("read()","EquationSystems"); 00363 00364 // Localize each system's data 00365 this->update(); 00366 } 00367 00368 00369 00370 void EquationSystems::write(const std::string& name, 00371 const unsigned int write_flags) const 00372 { 00373 libMeshEnums::XdrMODE mode = WRITE; 00374 if (name.find(".xdr") != std::string::npos) 00375 mode = ENCODE; 00376 this->write(name, mode, write_flags); 00377 } 00378 00379 00380 00381 void EquationSystems::write(const std::string& name, 00382 const libMeshEnums::XdrMODE mode, 00383 const unsigned int write_flags) const 00384 { 00448 // the EquationSystems::write() method should look constant, 00449 // but we need to assign a temporary numbering to the nodes 00450 // and elements in the mesh, which requires that we abuse const_cast 00451 { 00452 MeshBase &mesh = const_cast<MeshBase&>(this->get_mesh()); 00453 MeshTools::Private::globally_renumber_nodes_and_elements(mesh); 00454 } 00455 00456 // set booleans from write_flags argument 00457 const bool write_data = write_flags & EquationSystems::WRITE_DATA; 00458 const bool write_additional_data = write_flags & EquationSystems::WRITE_ADDITIONAL_DATA; 00459 00460 // always write parallel files if we're instructed to write in 00461 // parallel 00462 const bool write_parallel_files = 00463 (write_flags & EquationSystems::WRITE_PARALLEL_FILES) || 00464 // but also write parallel files if we haven't been instructed to 00465 // write in serial and we're on a distributed mesh 00466 (!(write_flags & EquationSystems::WRITE_SERIAL_FILES) && 00467 !this->get_mesh().is_serial()); 00468 00469 // New scope so that io will close before we try to zip the file 00470 { 00471 Xdr io((libMesh::processor_id()==0) ? name : "", mode); 00472 libmesh_assert (io.writing()); 00473 00474 START_LOG("write()","EquationSystems"); 00475 00476 const unsigned int proc_id = libMesh::processor_id(); 00477 unsigned int n_sys = this->n_systems(); 00478 00479 std::map<std::string, System*>::const_iterator 00480 pos = _systems.begin(); 00481 00482 std::string comment; 00483 char buf[256]; 00484 00485 // set the version number in the Xdr object 00486 io.set_version(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, 00487 LIBMESH_MINOR_VERSION, 00488 LIBMESH_MICRO_VERSION)); 00489 00490 // Only write the header information 00491 // if we are processor 0. 00492 if (proc_id == 0) 00493 { 00494 // 1.) 00495 // Write the version header 00496 std::string version("libMesh-" + libMesh::get_io_compatibility_version()); 00497 if (write_parallel_files) version += " parallel"; 00498 00499 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00500 version += " with infinite elements"; 00501 #endif 00502 io.data (version, "# File Format Identifier"); 00503 00504 // 2.) 00505 // Write the number of equation systems 00506 io.data (n_sys, "# No. of Equation Systems"); 00507 00508 while (pos != _systems.end()) 00509 { 00510 // 3.) 00511 // Write the name of the sys_num-th system 00512 { 00513 const unsigned int sys_num = pos->second->number(); 00514 std::string sys_name = pos->first; 00515 00516 comment = "# Name, System No. "; 00517 std::sprintf(buf, "%d", sys_num); 00518 comment += buf; 00519 00520 io.data (sys_name, comment.c_str()); 00521 } 00522 00523 // 4.) 00524 // Write the type of system handled 00525 { 00526 const unsigned int sys_num = pos->second->number(); 00527 std::string sys_type = pos->second->system_type(); 00528 00529 comment = "# Type, System No. "; 00530 std::sprintf(buf, "%d", sys_num); 00531 comment += buf; 00532 00533 io.data (sys_type, comment.c_str()); 00534 } 00535 00536 // 5.) - 9.) 00537 // Let System::write_header() do the job 00538 pos->second->write_header (io, version, write_additional_data); 00539 00540 ++pos; 00541 } 00542 } 00543 00544 // Start from the first system, again, 00545 // to write vectors to disk, if wanted 00546 if (write_data) 00547 { 00548 // open a parallel buffer if warranted. 00549 Xdr local_io (write_parallel_files ? local_file_name(name) : "", mode); 00550 00551 for (pos = _systems.begin(); pos != _systems.end(); ++pos) 00552 { 00553 // 10.) + 11.) 00554 if (write_parallel_files) 00555 pos->second->write_parallel_data (local_io,write_additional_data); 00556 else 00557 pos->second->write_serialized_data (io,write_additional_data); 00558 } 00559 } 00560 00561 STOP_LOG("write()","EquationSystems"); 00562 } 00563 00564 // the EquationSystems::write() method should look constant, 00565 // but we need to undo the temporary numbering of the nodes 00566 // and elements in the mesh, which requires that we abuse const_cast 00567 const_cast<MeshBase&>(_mesh).fix_broken_node_and_element_numbering(); 00568 } 00569 00570 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: