$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 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 unsigned int processor_id, 00046 const std::string &name) 00047 { 00048 std::string basename(name); 00049 char buf[256]; 00050 00051 if (basename.size() - basename.rfind(".bz2") == 4) 00052 { 00053 basename.erase(basename.end()-4, basename.end()); 00054 std::sprintf(buf, "%s.%04u.bz2", basename.c_str(), processor_id); 00055 } 00056 else if (basename.size() - basename.rfind(".gz") == 3) 00057 { 00058 basename.erase(basename.end()-3, basename.end()); 00059 std::sprintf(buf, "%s.%04u.gz", basename.c_str(), processor_id); 00060 } 00061 else 00062 std::sprintf(buf, "%s.%04u", basename.c_str(), processor_id); 00063 00064 return std::string(buf); 00065 } 00066 } 00067 00068 00069 00070 00071 // ------------------------------------------------------------ 00072 // EquationSystem class implementation 00073 template <typename InValType> 00074 void EquationSystems::read (const std::string& name, 00075 const unsigned int read_flags, 00076 bool partition_agnostic) 00077 { 00078 XdrMODE mode = READ; 00079 if (name.find(".xdr") != std::string::npos) 00080 mode = DECODE; 00081 this->read(name, mode, read_flags, partition_agnostic); 00082 00083 #ifdef LIBMESH_ENABLE_AMR 00084 MeshRefinement mesh_refine(_mesh); 00085 mesh_refine.clean_refinement_flags(); 00086 #endif 00087 } 00088 00089 00090 00091 template <typename InValType> 00092 void EquationSystems::read (const std::string& name, 00093 const XdrMODE mode, 00094 const unsigned int read_flags, 00095 bool partition_agnostic) 00096 { 00097 #ifdef LIBMESH_ENABLE_EXCEPTIONS 00098 00099 // If we have exceptions enabled we can be considerate and try 00100 // to read old restart files which contain infinite element 00101 // information but do not have the " with infinite elements" 00102 // string in the version information. 00103 00104 // First try the read the user requested 00105 try 00106 { 00107 this->_read_impl<InValType> (name, mode, read_flags, partition_agnostic); 00108 } 00109 00110 // If that fails, try it again but explicitly request we look for infinite element info 00111 catch (...) 00112 { 00113 libMesh::out << "\n*********************************************************************\n" 00114 << "READING THE FILE \"" << name << "\" FAILED.\n" 00115 << "It is possible this file contains infinite element information,\n" 00116 << "but the version string does not contain \" with infinite elements\"\n" 00117 << "Let's try this again, but looking for infinite element information...\n" 00118 << "*********************************************************************\n" 00119 << std::endl; 00120 00121 try 00122 { 00123 this->_read_impl<InValType> (name, mode, read_flags | EquationSystems::TRY_READ_IFEMS, partition_agnostic); 00124 } 00125 00126 // If all that failed, we are out of ideas here... 00127 catch (...) 00128 { 00129 libMesh::out << "\n*********************************************************************\n" 00130 << "Well, at least we tried!\n" 00131 << "Good Luck!!\n" 00132 << "*********************************************************************\n" 00133 << std::endl; 00134 throw; 00135 } 00136 } 00137 00138 #else 00139 00140 // no exceptions - cross your fingers... 00141 this->_read_impl<InValType> (name, mode, read_flags, partition_agnostic); 00142 00143 #endif // #ifdef LIBMESH_ENABLE_EXCEPTIONS 00144 00145 #ifdef LIBMESH_ENABLE_AMR 00146 MeshRefinement mesh_refine(_mesh); 00147 mesh_refine.clean_refinement_flags(); 00148 #endif 00149 } 00150 00151 00152 00153 template <typename InValType> 00154 void EquationSystems::_read_impl (const std::string& name, 00155 const XdrMODE mode, 00156 const unsigned int read_flags, 00157 bool partition_agnostic) 00158 { 00222 // Set booleans from the read_flags argument 00223 const bool read_header = read_flags & EquationSystems::READ_HEADER; 00224 const bool read_data = read_flags & EquationSystems::READ_DATA; 00225 const bool read_additional_data = read_flags & EquationSystems::READ_ADDITIONAL_DATA; 00226 const bool read_legacy_format = read_flags & EquationSystems::READ_LEGACY_FORMAT; 00227 const bool try_read_ifems = read_flags & EquationSystems::TRY_READ_IFEMS; 00228 const bool read_basic_only = read_flags & EquationSystems::READ_BASIC_ONLY; 00229 bool read_parallel_files = false; 00230 00231 std::map<std::string, System*> xda_systems; 00232 00233 // This will unzip a file with .bz2 as the extension, otherwise it 00234 // simply returns the name if the file need not be unzipped. 00235 Xdr io ((this->processor_id() == 0) ? name : "", mode); 00236 libmesh_assert (io.reading()); 00237 00238 { 00239 // 1.) 00240 // Read the version header. 00241 std::string version = "legacy"; 00242 if (!read_legacy_format) 00243 { 00244 if (this->processor_id() == 0) io.data(version); 00245 this->comm().broadcast(version); 00246 00247 // All processors have the version header, if it does not contain 00248 // "libMesh" something then it is a legacy file. 00249 std::string::size_type lm_pos = version.find("libMesh"); 00250 if (!(lm_pos < version.size())) 00251 { 00252 io.close(); 00253 00254 // Recursively call this read() function but with the 00255 // EquationSystems::READ_LEGACY_FORMAT bit set. 00256 this->read (name, mode, (read_flags | EquationSystems::READ_LEGACY_FORMAT), partition_agnostic); 00257 return; 00258 } 00259 00260 // Figure out the libMesh version that created this file 00261 std::istringstream iss(version.substr(lm_pos + 8)); 00262 int ver_major = 0, ver_minor = 0, ver_patch = 0; 00263 char dot; 00264 iss >> ver_major >> dot >> ver_minor >> dot >> ver_patch; 00265 io.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch)); 00266 00267 00268 read_parallel_files = (version.rfind(" parallel") < version.size()); 00269 00270 // If requested that we try to read infinite element information, 00271 // and the string " with infinite elements" is not in the version, 00272 // then tack it on. This is for compatibility reading ifem 00273 // files written prior to 11/10/2008 - BSK 00274 if (try_read_ifems) 00275 if (!(version.rfind(" with infinite elements") < version.size())) 00276 version += " with infinite elements"; 00277 00278 } 00279 else 00280 libmesh_deprecated(); 00281 00282 START_LOG("read()","EquationSystems"); 00283 00284 // 2.) 00285 // Read the number of equation systems 00286 unsigned int n_sys=0; 00287 if (this->processor_id() == 0) io.data (n_sys); 00288 this->comm().broadcast(n_sys); 00289 00290 for (unsigned int sys=0; sys<n_sys; sys++) 00291 { 00292 // 3.) 00293 // Read the name of the sys-th equation system 00294 std::string sys_name; 00295 if (this->processor_id() == 0) io.data (sys_name); 00296 this->comm().broadcast(sys_name); 00297 00298 // 4.) 00299 // Read the type of the sys-th equation system 00300 std::string sys_type; 00301 if (this->processor_id() == 0) io.data (sys_type); 00302 this->comm().broadcast(sys_type); 00303 00304 if (read_header) 00305 this->add_system (sys_type, sys_name); 00306 00307 // 5.) - 9.) 00308 // Let System::read_header() do the job 00309 System& new_system = this->get_system(sys_name); 00310 new_system.read_header (io, 00311 version, 00312 read_header, 00313 read_additional_data, 00314 read_legacy_format); 00315 00316 xda_systems.insert(std::make_pair(sys_name, &new_system)); 00317 00318 // If we're only creating "basic" systems, we need to tell 00319 // each system that before we call init() later. 00320 if (read_basic_only) 00321 new_system.set_basic_system_only(); 00322 } 00323 } 00324 00325 00326 00327 // Now we are ready to initialize the underlying data 00328 // structures. This will initialize the vectors for 00329 // storage, the dof_map, etc... 00330 if (read_header) 00331 this->init(); 00332 00333 // 10.) & 11.) 00334 // Read and set the numeric vector values 00335 if (read_data) 00336 { 00337 // the EquationSystems::read() method should look constant from the mesh 00338 // perspective, but we need to assign a temporary numbering to the nodes 00339 // and elements in the mesh, which requires that we abuse const_cast 00340 if (!read_legacy_format && partition_agnostic) 00341 { 00342 MeshBase &mesh = const_cast<MeshBase&>(this->get_mesh()); 00343 MeshTools::Private::globally_renumber_nodes_and_elements(mesh); 00344 } 00345 00346 Xdr local_io (read_parallel_files ? local_file_name(this->processor_id(),name) : "", mode); 00347 00348 std::map<std::string, System*>::iterator 00349 pos = xda_systems.begin(); 00350 00351 for (; pos != xda_systems.end(); ++pos) 00352 if (read_legacy_format) 00353 { 00354 libmesh_deprecated(); 00355 pos->second->read_legacy_data (io, read_additional_data); 00356 } 00357 else 00358 if (read_parallel_files) 00359 pos->second->read_parallel_data<InValType> (local_io, read_additional_data); 00360 else 00361 pos->second->read_serialized_data<InValType> (io, read_additional_data); 00362 00363 00364 // Undo the temporary numbering. 00365 if (!read_legacy_format && partition_agnostic) 00366 _mesh.fix_broken_node_and_element_numbering(); 00367 } 00368 00369 STOP_LOG("read()","EquationSystems"); 00370 00371 // Localize each system's data 00372 this->update(); 00373 } 00374 00375 00376 00377 void EquationSystems::write(const std::string& name, 00378 const unsigned int write_flags, 00379 bool partition_agnostic) const 00380 { 00381 XdrMODE mode = WRITE; 00382 if (name.find(".xdr") != std::string::npos) 00383 mode = ENCODE; 00384 this->write(name, mode, write_flags, partition_agnostic); 00385 } 00386 00387 00388 00389 void EquationSystems::write(const std::string& name, 00390 const XdrMODE mode, 00391 const unsigned int write_flags, 00392 bool partition_agnostic) const 00393 { 00457 // the EquationSystems::write() method should look constant, 00458 // but we need to assign a temporary numbering to the nodes 00459 // and elements in the mesh, which requires that we abuse const_cast 00460 if(partition_agnostic) 00461 { 00462 MeshBase &mesh = const_cast<MeshBase&>(this->get_mesh()); 00463 MeshTools::Private::globally_renumber_nodes_and_elements(mesh); 00464 } 00465 00466 // set booleans from write_flags argument 00467 const bool write_data = write_flags & EquationSystems::WRITE_DATA; 00468 const bool write_additional_data = write_flags & EquationSystems::WRITE_ADDITIONAL_DATA; 00469 00470 // always write parallel files if we're instructed to write in 00471 // parallel 00472 const bool write_parallel_files = 00473 (write_flags & EquationSystems::WRITE_PARALLEL_FILES) || 00474 // but also write parallel files if we haven't been instructed to 00475 // write in serial and we're on a distributed mesh 00476 (!(write_flags & EquationSystems::WRITE_SERIAL_FILES) && 00477 !this->get_mesh().is_serial()); 00478 00479 // New scope so that io will close before we try to zip the file 00480 { 00481 Xdr io((this->processor_id()==0) ? name : "", mode); 00482 libmesh_assert (io.writing()); 00483 00484 START_LOG("write()","EquationSystems"); 00485 00486 const unsigned int proc_id = this->processor_id(); 00487 unsigned int n_sys = this->n_systems(); 00488 00489 std::map<std::string, System*>::const_iterator 00490 pos = _systems.begin(); 00491 00492 // set the version number in the Xdr object 00493 io.set_version(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, 00494 LIBMESH_MINOR_VERSION, 00495 LIBMESH_MICRO_VERSION)); 00496 00497 // Only write the header information 00498 // if we are processor 0. 00499 if (proc_id == 0) 00500 { 00501 std::string comment; 00502 char buf[256]; 00503 00504 // 1.) 00505 // Write the version header 00506 std::string version("libMesh-" + libMesh::get_io_compatibility_version()); 00507 if (write_parallel_files) version += " parallel"; 00508 00509 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00510 version += " with infinite elements"; 00511 #endif 00512 io.data (version, "# File Format Identifier"); 00513 00514 // 2.) 00515 // Write the number of equation systems 00516 io.data (n_sys, "# No. of Equation Systems"); 00517 00518 while (pos != _systems.end()) 00519 { 00520 // 3.) 00521 // Write the name of the sys_num-th system 00522 { 00523 const unsigned int sys_num = pos->second->number(); 00524 std::string sys_name = pos->first; 00525 00526 comment = "# Name, System No. "; 00527 std::sprintf(buf, "%u", sys_num); 00528 comment += buf; 00529 00530 io.data (sys_name, comment.c_str()); 00531 } 00532 00533 // 4.) 00534 // Write the type of system handled 00535 { 00536 const unsigned int sys_num = pos->second->number(); 00537 std::string sys_type = pos->second->system_type(); 00538 00539 comment = "# Type, System No. "; 00540 std::sprintf(buf, "%u", sys_num); 00541 comment += buf; 00542 00543 io.data (sys_type, comment.c_str()); 00544 } 00545 00546 // 5.) - 9.) 00547 // Let System::write_header() do the job 00548 pos->second->write_header (io, version, write_additional_data); 00549 00550 ++pos; 00551 } 00552 } 00553 00554 // Start from the first system, again, 00555 // to write vectors to disk, if wanted 00556 if (write_data) 00557 { 00558 // open a parallel buffer if warranted. 00559 Xdr local_io (write_parallel_files ? local_file_name(this->processor_id(),name) : "", mode); 00560 00561 for (pos = _systems.begin(); pos != _systems.end(); ++pos) 00562 { 00563 // 10.) + 11.) 00564 if (write_parallel_files) 00565 pos->second->write_parallel_data (local_io,write_additional_data); 00566 else 00567 pos->second->write_serialized_data (io,write_additional_data); 00568 } 00569 } 00570 00571 STOP_LOG("write()","EquationSystems"); 00572 } 00573 00574 // the EquationSystems::write() method should look constant, 00575 // but we need to undo the temporary numbering of the nodes 00576 // and elements in the mesh, which requires that we abuse const_cast 00577 if(partition_agnostic) 00578 const_cast<MeshBase&>(_mesh).fix_broken_node_and_element_numbering(); 00579 } 00580 00581 00582 00583 // template specialization 00584 00585 template void EquationSystems::read<Number> (const std::string& name, const unsigned int read_flags, bool partition_agnostic); 00586 template void EquationSystems::read<Number> (const std::string& name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic); 00587 template void EquationSystems::_read_impl<Number> (const std::string& name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic); 00588 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 00589 template void EquationSystems::read<Real> (const std::string& name, const unsigned int read_flags, bool partition_agnostic); 00590 template void EquationSystems::read<Real> (const std::string& name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic); 00591 template void EquationSystems::_read_impl<Real> (const std::string& name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic); 00592 #endif 00593 00594 } // namespace libMesh