$extrastylesheet
checkpoint_io.C
Go to the documentation of this file.
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 #include "libmesh/checkpoint_io.h"
00019 
00020 // C++ includes
00021 #include <iostream>
00022 #include <iomanip>
00023 #include <cstdio>
00024 #include <vector>
00025 #include <string>
00026 #include <fstream>
00027 #include <sstream> // for ostringstream
00028 
00029 // Local includes
00030 #include "libmesh/xdr_io.h"
00031 #include "libmesh/legacy_xdr_io.h"
00032 #include "libmesh/xdr_cxx.h"
00033 #include "libmesh/enum_xdr_mode.h"
00034 #include "libmesh/mesh_base.h"
00035 #include "libmesh/node.h"
00036 #include "libmesh/elem.h"
00037 #include "libmesh/boundary_info.h"
00038 #include "libmesh/parallel.h"
00039 #include "libmesh/mesh_tools.h"
00040 #include "libmesh/partitioner.h"
00041 #include "libmesh/libmesh_logging.h"
00042 #include "libmesh/mesh_communication.h"
00043 #include "libmesh/parallel_mesh.h"
00044 
00045 namespace libMesh
00046 {
00047 
00048 // ------------------------------------------------------------
00049 // CheckpointIO members
00050 CheckpointIO::CheckpointIO (MeshBase& mesh, const bool binary_in) :
00051   MeshInput<MeshBase> (mesh,/* is_parallel_format = */ true),
00052   MeshOutput<MeshBase>(mesh,/* is_parallel_format = */ true),
00053   ParallelObject      (mesh),
00054   _binary             (binary_in),
00055   _version            ("checkpoint-1.0")
00056 {
00057 }
00058 
00059 
00060 
00061 CheckpointIO::CheckpointIO (const MeshBase& mesh, const bool binary_in) :
00062   MeshOutput<MeshBase>(mesh,/* is_parallel_format = */ true),
00063   ParallelObject      (mesh),
00064   _binary (binary_in)
00065 {
00066 }
00067 
00068 
00069 
00070 CheckpointIO::~CheckpointIO ()
00071 {
00072 }
00073 
00074 
00075 
00076 
00077 void CheckpointIO::write (const std::string& name)
00078 {
00079   START_LOG("write()","CheckpointIO");
00080 
00081   // convenient reference to our mesh
00082   const MeshBase &mesh = MeshOutput<MeshBase>::mesh();
00083 
00084   // Try to dynamic cast the mesh to see if it's a ParallelMesh object
00085   // Note: Just using is_serial() is not good enough because the Mesh won't
00086   // have been prepared yet when is when that flag gets set to false... sigh.
00087   bool parallel_mesh = dynamic_cast<const ParallelMesh*>(&mesh);
00088 
00089   // If this is a serial mesh then we're only going to write it on processor 0
00090   if(parallel_mesh || this->processor_id() == 0)
00091     {
00092       std::ostringstream file_name_stream;
00093 
00094       file_name_stream << name;
00095 
00096       if(parallel_mesh)
00097         file_name_stream << "-" << this->processor_id();
00098 
00099       Xdr io (file_name_stream.str(), this->binary() ? ENCODE : WRITE);
00100 
00101       // write the version
00102       io.data(_version, "# version");
00103 
00104       // Write out whether or not this is a serial mesh (helps with error checking on read)
00105       {
00106         unsigned int parallel = parallel_mesh;
00107         io.data(parallel, "# parallel");
00108       }
00109 
00110       // If we're writing out a parallel mesh then we need to write the number of processors
00111       // so we can check it upon reading the file
00112       if(parallel_mesh)
00113         {
00114           largest_id_type n_procs = this->n_processors();
00115           io.data(n_procs, "# n_procs");
00116         }
00117 
00118       // write subdomain names
00119       this->write_subdomain_names(io);
00120 
00121       // write the nodal locations
00122       this->write_nodes (io);
00123 
00124       // write connectivity
00125       this->write_connectivity (io);
00126 
00127       // write the boundary condition information
00128       this->write_bcs (io);
00129 
00130       // write the nodeset information
00131       this->write_nodesets (io);
00132 
00133       // pause all processes until the writing ends -- this will
00134       // protect for the pathological case where a write is
00135       // followed immediately by a read.  The write must be
00136       // guaranteed to complete first.
00137       io.close();
00138     }
00139 
00140   this->comm().barrier();
00141 
00142   STOP_LOG("write()","CheckpointIO");
00143 }
00144 
00145 
00146 
00147 void CheckpointIO::write_subdomain_names(Xdr &io) const
00148 {
00149   {
00150     const MeshBase &mesh = MeshOutput<MeshBase>::mesh();
00151 
00152     const std::map<subdomain_id_type, std::string> & subdomain_map = mesh.get_subdomain_name_map();
00153 
00154     std::vector<header_id_type> subdomain_ids;   subdomain_ids.reserve(subdomain_map.size());
00155     std::vector<std::string>  subdomain_names; subdomain_names.reserve(subdomain_map.size());
00156 
00157     // We need to loop over the map and make sure that there aren't any invalid entries.  Since we
00158     // return writable references in mesh_base, it's possible for the user to leave some entity names
00159     // blank.  We can't write those to the XDA file.
00160     header_id_type n_subdomain_names = 0;
00161     std::map<subdomain_id_type, std::string>::const_iterator it_end = subdomain_map.end();
00162     for (std::map<subdomain_id_type, std::string>::const_iterator it = subdomain_map.begin(); it != it_end; ++it)
00163       {
00164         if (!it->second.empty())
00165           {
00166             n_subdomain_names++;
00167             subdomain_ids.push_back(it->first);
00168             subdomain_names.push_back(it->second);
00169           }
00170       }
00171 
00172     io.data(n_subdomain_names, "# subdomain id to name map");
00173     // Write out the ids and names in two vectors
00174     if (n_subdomain_names)
00175       {
00176         io.data(subdomain_ids);
00177         io.data(subdomain_names);
00178       }
00179   }
00180 }
00181 
00182 
00183 
00184 void CheckpointIO::write_nodes (Xdr &io) const
00185 {
00186   // convenient reference to our mesh
00187   const MeshBase &mesh = MeshOutput<MeshBase>::mesh();
00188 
00189   MeshBase::const_node_iterator
00190     it  = mesh.nodes_begin(),
00191     end = mesh.nodes_end();
00192 
00193   unsigned int n_nodes_here = MeshTools::n_nodes(it, end);
00194 
00195   io.data(n_nodes_here, "# n_nodes on proc");
00196 
00197   it = mesh.nodes_begin();
00198 
00199   // Will hold the node id and pid
00200   std::vector<largest_id_type> id_pid(2);
00201 
00202   // For the coordinates
00203   std::vector<Real> coords(LIBMESH_DIM);
00204 
00205   for(; it != end; ++it)
00206     {
00207       Node & node = *(*it);
00208 
00209       id_pid[0] = node.id();
00210       id_pid[1] = node.processor_id();
00211 
00212       io.data_stream(&id_pid[0], 2, 2);
00213 
00214 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00215       largest_id_type unique_id = node.unique_id();
00216 
00217       io.data(unique_id, "# unique id");
00218 #endif
00219 
00220       coords[0] = node(0);
00221 
00222 #if LIBMESH_DIM > 1
00223       coords[1] = node(1);
00224 #endif
00225 
00226 #if LIBMESH_DIM > 2
00227       coords[2] = node(2);
00228 #endif
00229 
00230       io.data_stream(&coords[0], LIBMESH_DIM, 3);
00231     }
00232 }
00233 
00234 
00235 
00236 void CheckpointIO::write_connectivity (Xdr &io) const
00237 {
00238   libmesh_assert (io.writing());
00239 
00240   // convenient reference to our mesh
00241   const MeshBase &mesh = MeshOutput<MeshBase>::mesh();
00242 
00243   // We will only write active elements and their parents.
00244   unsigned int n_active_levels = n_active_levels_on_processor(mesh);
00245 
00246   std::vector<xdr_id_type> n_elem_at_level(n_active_levels);
00247 
00248   // Find the number of elements at each level
00249   for (unsigned int level=0; level<n_active_levels; level++)
00250     {
00251       MeshBase::const_element_iterator it  = mesh.level_elements_begin(level);
00252       MeshBase::const_element_iterator end = mesh.level_elements_end(level);
00253 
00254       n_elem_at_level[level] = MeshTools::n_elem(it, end);
00255     }
00256 
00257   io.data(n_active_levels, "# n_active_levels");
00258 
00259   for(unsigned int level=0; level < n_active_levels; level++)
00260     {
00261       std::ostringstream comment;
00262       comment << "# n_elem at level ";
00263       comment << level ;
00264       io.data (n_elem_at_level[level], comment.str().c_str());
00265 
00266       MeshBase::const_element_iterator it  = mesh.level_elements_begin(level);
00267       MeshBase::const_element_iterator end = mesh.level_elements_end(level);
00268       for (; it != end; ++it)
00269         {
00270           Elem & elem = *(*it);
00271 
00272           unsigned int n_nodes = elem.n_nodes();
00273 
00274           // id type pid subdomain_id parent_id
00275           std::vector<largest_id_type> elem_data(5);
00276 
00277           elem_data[0] = elem.id();
00278           elem_data[1] = elem.type();
00279           elem_data[2] = elem.processor_id();
00280           elem_data[3] = elem.subdomain_id();
00281 
00282           if(elem.parent() != NULL)
00283             elem_data[4] = elem.parent()->id();
00284           else
00285             elem_data[4] = DofObject::invalid_processor_id;
00286 
00287           std::vector<largest_id_type> conn_data(n_nodes);
00288 
00289           for(unsigned int i=0; i<n_nodes; i++)
00290             conn_data[i] = elem.node(i);
00291 
00292           io.data_stream(&elem_data[0],
00293                          cast_int<unsigned int>(elem_data.size()),
00294                          cast_int<unsigned int>(elem_data.size()));
00295 
00296 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00297           largest_id_type unique_id = elem.unique_id();
00298 
00299           io.data(unique_id, "# unique id");
00300 #endif
00301 
00302 #ifdef LIBMESH_ENABLE_AMR
00303           unsigned int p_level = elem.p_level();
00304 
00305           io.data(p_level, "# p_level");
00306 #endif
00307 
00308           io.data_stream(&conn_data[0],
00309                          cast_int<unsigned int>(conn_data.size()),
00310                          cast_int<unsigned int>(conn_data.size()));
00311         }
00312     }
00313 }
00314 
00315 
00316 
00317 void CheckpointIO::write_bcs (Xdr &io) const
00318 {
00319   libmesh_assert (io.writing());
00320 
00321   // convenient reference to our mesh
00322   const MeshBase &mesh = MeshOutput<MeshBase>::mesh();
00323 
00324   // and our boundary info object
00325   const BoundaryInfo &boundary_info = mesh.get_boundary_info();
00326 
00327   // Version 0.9.2+ introduces entity names
00328   write_bc_names(io, boundary_info, true);  // sideset names
00329   write_bc_names(io, boundary_info, false); // nodeset names
00330 
00331   std::vector<dof_id_type> element_id_list;
00332   std::vector<unsigned short int> side_list;
00333   std::vector<boundary_id_type> bc_id_list;
00334 
00335   boundary_info.build_side_list(element_id_list, side_list, bc_id_list);
00336 
00337   io.data(element_id_list, "# element ids for bcs");
00338   io.data(side_list, "# sides of elements for bcs");
00339   io.data(bc_id_list, "# bc ids");
00340 }
00341 
00342 
00343 
00344 void CheckpointIO::write_nodesets (Xdr &io) const
00345 {
00346   libmesh_assert (io.writing());
00347 
00348   // convenient reference to our mesh
00349   const MeshBase &mesh = MeshOutput<MeshBase>::mesh();
00350 
00351   // and our boundary info object
00352   const BoundaryInfo &boundary_info = mesh.get_boundary_info();
00353 
00354   std::vector<dof_id_type> node_id_list;
00355   std::vector<boundary_id_type> bc_id_list;
00356 
00357   boundary_info.build_node_list(node_id_list, bc_id_list);
00358 
00359   io.data(node_id_list, "# node id list");
00360   io.data(bc_id_list, "# nodeset bc id list");
00361 }
00362 
00363 
00364 
00365 void CheckpointIO::write_bc_names (Xdr &io, const BoundaryInfo & info, bool is_sideset) const
00366 {
00367   const std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
00368     info.get_sideset_name_map() : info.get_nodeset_name_map();
00369 
00370   std::vector<boundary_id_type> boundary_ids;   boundary_ids.reserve(boundary_map.size());
00371   std::vector<std::string>  boundary_names; boundary_names.reserve(boundary_map.size());
00372 
00373   // We need to loop over the map and make sure that there aren't any invalid entries.  Since we
00374   // return writable references in boundary_info, it's possible for the user to leave some entity names
00375   // blank.  We can't write those to the XDA file.
00376   header_id_type n_boundary_names = 0;
00377   std::map<boundary_id_type, std::string>::const_iterator it_end = boundary_map.end();
00378   for (std::map<boundary_id_type, std::string>::const_iterator it = boundary_map.begin(); it != it_end; ++it)
00379     {
00380       if (!it->second.empty())
00381         {
00382           n_boundary_names++;
00383           boundary_ids.push_back(it->first);
00384           boundary_names.push_back(it->second);
00385         }
00386     }
00387 
00388   if (is_sideset)
00389     io.data(n_boundary_names, "# sideset id to name map");
00390   else
00391     io.data(n_boundary_names, "# nodeset id to name map");
00392   // Write out the ids and names in two vectors
00393   if (n_boundary_names)
00394     {
00395       io.data(boundary_ids);
00396       io.data(boundary_names);
00397     }
00398 }
00399 
00400 
00401 
00402 void CheckpointIO::read (const std::string& name)
00403 {
00404   START_LOG("read()","CheckpointIO");
00405 
00406   MeshBase &mesh = MeshInput<MeshBase>::mesh();
00407 
00408   // Try to dynamic cast the mesh to see if it's a ParallelMesh object
00409   // Note: Just using is_serial() is not good enough because the Mesh won't
00410   // have been prepared yet when is when that flag gets set to false... sigh.
00411   bool parallel_mesh = dynamic_cast<ParallelMesh*>(&mesh);
00412 
00413   // If this is a serial mesh then we're going to only read it on processor 0 and broadcast it
00414   if(parallel_mesh || this->processor_id() == 0)
00415     {
00416       std::ostringstream file_name_stream;
00417 
00418       file_name_stream << name;
00419 
00420       if(parallel_mesh)
00421         file_name_stream << "-" << this->processor_id();
00422 
00423       {
00424         std::ifstream in (file_name_stream.str().c_str());
00425 
00426         if (!in.good())
00427           libmesh_error_msg("ERROR: cannot locate specified file:\n\t" << file_name_stream.str());
00428       }
00429 
00430       Xdr io (file_name_stream.str(), this->binary() ? DECODE : READ);
00431 
00432       // read the version
00433       io.data (_version);
00434 
00435       // Check if the mesh we're reading is the same as the one that was written
00436       {
00437         unsigned int parallel;
00438         io.data(parallel, "# parallel");
00439 
00440         if(static_cast<unsigned int>(parallel_mesh) != parallel)
00441           libmesh_error_msg("Attempted to utilize a checkpoint file with an incompatible mesh distribution!");
00442       }
00443 
00444       // If this is a parallel mesh then we need to check to ensure we're reading this on the same number of procs
00445       if(parallel_mesh)
00446         {
00447           largest_id_type n_procs;
00448           io.data(n_procs, "# n_procs");
00449 
00450           if(n_procs != this->n_processors())
00451             libmesh_error_msg("Attempted to utilize a checkpoint file on " << this->n_processors() << " processors but it was written using " << n_procs << "!!");
00452         }
00453 
00454       // read subdomain names
00455       this->read_subdomain_names(io);
00456 
00457       // read the nodal locations
00458       this->read_nodes (io);
00459 
00460       // read connectivity
00461       this->read_connectivity (io);
00462 
00463       // read the boundary conditions
00464       this->read_bcs (io);
00465 
00466       // read the nodesets
00467       this->read_nodesets (io);
00468 
00469       io.close();
00470     }
00471 
00472   // If the mesh is serial then we only read it on processor 0 so we need to broadcast it
00473   if(!parallel_mesh)
00474     MeshCommunication().broadcast(mesh);
00475 
00476   STOP_LOG("read()","CheckpointIO");
00477 }
00478 
00479 
00480 
00481 void CheckpointIO::read_subdomain_names(Xdr &io)
00482 {
00483   MeshBase &mesh = MeshInput<MeshBase>::mesh();
00484 
00485   std::map<subdomain_id_type, std::string> & subdomain_map =
00486     mesh.set_subdomain_name_map();
00487 
00488   std::vector<header_id_type> subdomain_ids;
00489   subdomain_ids.reserve(subdomain_map.size());
00490 
00491   std::vector<std::string>  subdomain_names;
00492   subdomain_names.reserve(subdomain_map.size());
00493 
00494   header_id_type n_subdomain_names = 0;
00495   io.data(n_subdomain_names, "# subdomain id to name map");
00496 
00497   if(n_subdomain_names)
00498     {
00499       io.data(subdomain_ids);
00500       io.data(subdomain_names);
00501 
00502       for(unsigned int i=0; i<subdomain_ids.size(); i++)
00503         subdomain_map[cast_int<subdomain_id_type>(subdomain_ids[i])] =
00504           subdomain_names[i];
00505     }
00506 }
00507 
00508 
00509 
00510 void CheckpointIO::read_nodes (Xdr &io)
00511 {
00512   // convenient reference to our mesh
00513   MeshBase &mesh = MeshInput<MeshBase>::mesh();
00514 
00515   unsigned int n_nodes_here;
00516   io.data(n_nodes_here, "# n_nodes on proc");
00517 
00518   // Will hold the node id and pid
00519   std::vector<largest_id_type> id_pid(2);
00520 
00521   // For the coordinates
00522   std::vector<Real> coords(LIBMESH_DIM);
00523 
00524   for(unsigned int i=0; i<n_nodes_here; i++)
00525     {
00526       io.data_stream(&id_pid[0], 2, 2);
00527 
00528 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00529       largest_id_type unique_id = 0;
00530       io.data(unique_id, "# unique id");
00531 #endif
00532 
00533       io.data_stream(&coords[0], LIBMESH_DIM, LIBMESH_DIM);
00534 
00535       Point p;
00536       p(0) = coords[0];
00537 
00538 #if LIBMESH_DIM > 1
00539       p(1) = coords[1];
00540 #endif
00541 
00542 #if LIBMESH_DIM > 2
00543       p(2) = coords[2];
00544 #endif
00545 
00546 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00547       Node * node =
00548 #endif
00549         mesh.add_point(p, cast_int<dof_id_type>(id_pid[0]),
00550                        cast_int<processor_id_type>(id_pid[1]));
00551 
00552 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00553       node->set_unique_id() = unique_id;
00554 #endif
00555     }
00556 }
00557 
00558 
00559 
00560 void CheckpointIO::read_connectivity (Xdr &io)
00561 {
00562   // convenient reference to our mesh
00563   MeshBase &mesh = MeshInput<MeshBase>::mesh();
00564 
00565   unsigned int n_active_levels;
00566   io.data(n_active_levels, "# n_active_levels");
00567 
00568   // Keep track of the highest dimensional element we've added to the mesh
00569   unsigned int highest_elem_dim = 1;
00570 
00571   for(unsigned int level=0; level < n_active_levels; level++)
00572     {
00573       xdr_id_type n_elem_at_level = 0;
00574       io.data (n_elem_at_level, "");
00575 
00576       for (unsigned int i=0; i<n_elem_at_level; i++)
00577         {
00578           // id type pid subdomain_id parent_id
00579           std::vector<largest_id_type> elem_data(5);
00580           io.data_stream
00581             (&elem_data[0], cast_int<unsigned int>(elem_data.size()),
00582              cast_int<unsigned int>(elem_data.size()));
00583 
00584 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00585           largest_id_type unique_id = 0;
00586           io.data(unique_id, "# unique id");
00587 #endif
00588 
00589 #ifdef LIBMESH_ENABLE_AMR
00590           unsigned int p_level = 0;
00591 
00592           io.data(p_level, "# p_level");
00593 #endif
00594 
00595           unsigned int n_nodes = Elem::type_to_n_nodes_map[elem_data[1]];
00596 
00597           // Snag the node ids this element was connected to
00598           std::vector<largest_id_type> conn_data(n_nodes);
00599           io.data_stream
00600             (&conn_data[0], cast_int<unsigned int>(conn_data.size()),
00601              cast_int<unsigned int>(conn_data.size()));
00602 
00603           const dof_id_type id                 =
00604             cast_int<dof_id_type>      (elem_data[0]);
00605           const ElemType elem_type             =
00606             static_cast<ElemType>      (elem_data[1]);
00607           const processor_id_type proc_id      =
00608             cast_int<processor_id_type>(elem_data[2]);
00609           const subdomain_id_type subdomain_id =
00610             cast_int<subdomain_id_type>(elem_data[3]);
00611           const dof_id_type parent_id          =
00612             cast_int<dof_id_type>      (elem_data[4]);
00613 
00614           Elem * parent = (parent_id == DofObject::invalid_processor_id) ? NULL : mesh.elem(parent_id);
00615 
00616           // Create the element
00617           Elem * elem = Elem::build(elem_type, parent).release();
00618 
00619 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00620           elem->set_unique_id() = unique_id;
00621 #endif
00622 
00623           if(elem->dim() > highest_elem_dim)
00624             highest_elem_dim = elem->dim();
00625 
00626           elem->set_id()       = id;
00627           elem->processor_id() = proc_id;
00628           elem->subdomain_id() = subdomain_id;
00629 
00630 #ifdef LIBMESH_ENABLE_AMR
00631           elem->hack_p_level(p_level);
00632 
00633           // Set parent connections
00634           if(parent)
00635             {
00636               parent->add_child(elem);
00637               parent->set_refinement_flag (Elem::INACTIVE);
00638               elem->set_refinement_flag   (Elem::JUST_REFINED);
00639             }
00640 #endif
00641 
00642           libmesh_assert(elem->n_nodes() == conn_data.size());
00643 
00644           // Connect all the nodes to this element
00645           for (unsigned int n=0; n<conn_data.size(); n++)
00646             elem->set_node(n) =
00647               mesh.node_ptr(cast_int<dof_id_type>(conn_data[n]));
00648 
00649           mesh.add_elem(elem);
00650         }
00651     }
00652 
00653   mesh.set_mesh_dimension(cast_int<unsigned char>(highest_elem_dim));
00654 }
00655 
00656 
00657 
00658 void CheckpointIO::read_bcs (Xdr &io)
00659 {
00660   // convenient reference to our mesh
00661   MeshBase &mesh = MeshInput<MeshBase>::mesh();
00662 
00663   // and our boundary info object
00664   BoundaryInfo &boundary_info = mesh.get_boundary_info();
00665 
00666   // Version 0.9.2+ introduces entity names
00667   read_bc_names(io, boundary_info, true);  // sideset names
00668   read_bc_names(io, boundary_info, false); // nodeset names
00669 
00670   std::vector<dof_id_type> element_id_list;
00671   std::vector<unsigned short int> side_list;
00672   std::vector<boundary_id_type> bc_id_list;
00673 
00674   io.data(element_id_list, "# element ids for bcs");
00675   io.data(side_list, "# sides of elements for bcs");
00676   io.data(bc_id_list, "# bc ids");
00677 
00678   for(unsigned int i=0; i<element_id_list.size(); i++)
00679     boundary_info.add_side(element_id_list[i], side_list[i], bc_id_list[i]);
00680 }
00681 
00682 
00683 
00684 void CheckpointIO::read_nodesets (Xdr &io)
00685 {
00686   // convenient reference to our mesh
00687   MeshBase &mesh = MeshInput<MeshBase>::mesh();
00688 
00689   // and our boundary info object
00690   BoundaryInfo &boundary_info = mesh.get_boundary_info();
00691 
00692   std::vector<dof_id_type> node_id_list;
00693   std::vector<boundary_id_type> bc_id_list;
00694 
00695   io.data(node_id_list, "# node id list");
00696   io.data(bc_id_list, "# nodeset bc id list");
00697 
00698   for(unsigned int i=0; i<node_id_list.size(); i++)
00699     boundary_info.add_node(node_id_list[i], bc_id_list[i]);
00700 }
00701 
00702 
00703 
00704 void CheckpointIO::read_bc_names(Xdr &io, BoundaryInfo & info, bool is_sideset)
00705 {
00706   std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
00707     info.set_sideset_name_map() : info.set_nodeset_name_map();
00708 
00709   std::vector<boundary_id_type> boundary_ids;
00710   std::vector<std::string>  boundary_names;
00711 
00712   header_id_type n_boundary_names = 0;
00713 
00714   if (is_sideset)
00715     io.data(n_boundary_names, "# sideset id to name map");
00716   else
00717     io.data(n_boundary_names, "# nodeset id to name map");
00718 
00719   if (n_boundary_names)
00720     {
00721       io.data(boundary_ids);
00722       io.data(boundary_names);
00723     }
00724 
00725   // Add them back into the map
00726   for(unsigned int i=0; i<boundary_ids.size(); i++)
00727     boundary_map[boundary_ids[i]] = boundary_names[i];
00728 }
00729 
00730 
00731 unsigned int CheckpointIO::n_active_levels_on_processor(const MeshBase &mesh) const
00732 {
00733   unsigned int max_level = 0;
00734 
00735   MeshBase::const_element_iterator el = mesh.active_elements_begin();
00736   const MeshBase::const_element_iterator end_el = mesh.active_elements_end();
00737 
00738   for( ; el != end_el; ++el)
00739     max_level = std::max((*el)->level(), max_level);
00740 
00741   return max_level + 1;
00742 }
00743 
00744 } // namespace libMesh