19#include "libmesh/checkpoint_io.h"
20#include "libmesh/boundary_info.h"
21#include "libmesh/cell_c0polyhedron.h"
22#include "libmesh/distributed_mesh.h"
23#include "libmesh/elem.h"
24#include "libmesh/enum_to_string.h"
25#include "libmesh/enum_xdr_mode.h"
26#include "libmesh/face_c0polygon.h"
27#include "libmesh/libmesh_logging.h"
28#include "libmesh/mesh_base.h"
29#include "libmesh/mesh_communication.h"
30#include "libmesh/mesh_tools.h"
31#include "libmesh/node.h"
32#include "libmesh/parallel.h"
33#include "libmesh/partitioner.h"
34#include "libmesh/metis_partitioner.h"
35#include "libmesh/remote_elem.h"
36#include "libmesh/xdr_io.h"
37#include "libmesh/xdr_cxx.h"
38#include "libmesh/utility.h"
39#include "libmesh/int_range.h"
50#include <unordered_map>
51#include <unordered_set>
52#ifdef LIBMESH_HAVE_DIRECT_H
55#ifdef LIBMESH_HAVE_UNISTD_H
67 if (nsplits % size == 0)
69 nchunks = nsplits / size;
70 first_chunk = libMesh::cast_int<libMesh::processor_id_type>(nchunks * rank);
77 nchunks = libMesh::cast_int<libMesh::processor_id_type>(nsplits / size + 1);
78 first_chunk = libMesh::cast_int<libMesh::processor_id_type>(nchunks * rank);
82 nchunks = nsplits / size;
84 first_chunk = libMesh::cast_int<libMesh::processor_id_type>
85 (std::max((
int)((nchunks + 1) * (nsplits % size) + nchunks * (rank - nsplits % size)),
86 (1 - (
int)nchunks) * std::numeric_limits<int>::max()));
90std::string_view extension(std::string_view s)
92 auto pos = s.rfind(
".");
93 if (pos == std::string::npos)
95 return s.substr(pos, s.size() - pos);
100 return input_name +
"/" + std::to_string(n_procs);
106 return (split_dir(input_name, n_procs) +
"/header").append(extension(input_name));
110split_file(
const std::string & input_name,
114 return (split_dir(input_name, n_procs) +
"/split-" + std::to_string(n_procs) +
"-" +
115 std::to_string(proc_id)).append(extension(input_name));
123 (ret != 0 && ret != -1,
124 "Failed to create mesh split directory '" << input_name <<
"': " << std::strerror(ret));
126 auto dir_name = split_dir(input_name, n_procs);
129 libmesh_warning(
"In CheckpointIO::write, directory '"
130 << dir_name <<
"' already exists, overwriting contents.");
133 (ret != 0,
"Failed to create mesh split directory '" << dir_name <<
"': " << std::strerror(ret));
155 auto cpr = std::make_unique<CheckpointIO>(
mesh);
156 cpr->current_processor_ids().clear();
157 for (
processor_id_type i = my_first_chunk; i < my_first_chunk + my_num_chunks; i++)
158 cpr->current_processor_ids().push_back(i);
159 cpr->current_n_processors() = nsplits;
160 cpr->parallel() =
true;
173 _version (
"checkpoint-1.6"),
174 _my_processor_ids (1, processor_id()),
175 _my_n_processors (
mesh.is_replicated() ? 1 : n_processors())
185 _version (
"checkpoint-1.6"),
186 _my_processor_ids (1, processor_id()),
187 _my_n_processors (
mesh.is_replicated() ? 1 : n_processors())
195 std::string header_name;
204 std::ifstream in (header_name.c_str());
208 auto orig_header_name = header_name;
209 header_name = header_file(input_name, 1);
210 std::ifstream in2 (header_name.c_str());
211 libmesh_error_msg_if(!in2.good(),
212 "ERROR: Neither one of the following files can be located:\n\t'"
213 << orig_header_name <<
"' nor\n\t'" << input_name <<
"'\n"
214 <<
"If you are running a parallel job, double check that you've "
216 <<
"Note: One of paths above may refer to a valid directory on your "
217 <<
"system, however we are attempting to read a valid header file.");
224 std::string input_version;
225 io.
data(input_version);
239 input_n_procs = this->read_header<uint16_t>(header_name);
242 input_n_procs = this->read_header<uint32_t>(header_name);
245 input_n_procs = this->read_header<uint64_t>(header_name);
253 return cast_int<processor_id_type>(input_n_procs);
258 auto header = header_file(input_name, n_procs);
259 auto ret = std::remove(header.c_str());
261 libmesh_warning(
"Failed to clean up checkpoint header '" << header <<
"': " << std::strerror(ret));
265 auto split = split_file(input_name, n_procs, i);
266 ret = std::remove(split.c_str());
268 libmesh_warning(
"Failed to clean up checkpoint split file '" << split <<
"': " << std::strerror(ret));
271 auto dir = split_dir(input_name, n_procs);
272 ret = rmdir(dir.c_str());
274 libmesh_warning(
"Failed to clean up checkpoint split dir '" << dir <<
"': " << std::strerror(ret));
278 rmdir(input_name.c_str());
285 (this->
version().find(
"1.5") != std::string::npos) ||
286 (this->
version().find(
"1.6") != std::string::npos);
292 return (this->
version().find(
"1.6") != std::string::npos);
298 LOG_SCOPE(
"write()",
"CheckpointIO");
312 std::string header_file_name = header_file(name, use_n_procs);
313 make_dir(name, use_n_procs);
326 io.
data(data_size,
"# integer size");
332 io.
data(mesh_dimension,
"# dimensions");
346 io.
data(n_procs,
"# n_procs");
360 if (write_extra_integers)
363 io.
data(n_node_integers,
"# n_extra_integers per node");
365 std::vector<std::string> node_integer_names;
366 for (
unsigned int i=0; i != n_node_integers; ++i)
369 io.
data(node_integer_names);
372 io.
data(n_elem_integers,
"# n_extra_integers per elem");
374 std::vector<std::string> elem_integer_names;
375 for (
unsigned int i=0; i != n_elem_integers; ++i)
378 io.
data(elem_integer_names);
388 std::vector<processor_id_type> ids_to_write;
396 typedef std::remove_const<MeshBase::const_element_iterator::value_type>::type nc_v_t;
397 std::unordered_map<processor_id_type, std::vector<nc_v_t>> elements_on_pid;
403 elements_on_pid[p].clear();
404 auto eop_end = elements_on_pid.end();
405 for (
auto & elem :
mesh.element_ptr_range())
408 if (
auto eop_it = elements_on_pid.find(p);
410 eop_it->second.push_back(elem);
418 ids_to_write.push_back(0);
423 libmesh_error_msg(
"Cannot write serial checkpoint from distributed mesh");
429 std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>>
431 std::vector<std::tuple<dof_id_type, boundary_id_type>>
434 for (
const auto & my_pid : ids_to_write)
436 auto file_name = split_file(name, use_n_procs, my_pid);
439 std::set<const Elem *, CompareElemIdsByLevel> elements;
444 elements.insert(
mesh.elements_begin(),
mesh.elements_end());
462 if (
const auto elements_vec_it = elements_on_pid.find(p);
463 elements_vec_it != elements_on_pid.end())
465 auto & p_elements = elements_vec_it->second;
471 v_t * elempp = p_elements.
data();
472 v_t * elemend = elempp + p_elements.size();
485 (
mesh, p, active_pid_elements_begin,
486 active_pid_elements_end, elements);
488 pid_elements_end, elements);
506 this->
write_bcs (io, elements, bc_triples);
525 std::vector<largest_id_type> subdomain_ids; subdomain_ids.reserve(subdomain_map.size());
526 std::vector<std::string> subdomain_names; subdomain_names.reserve(subdomain_map.size());
532 for (
const auto & [
id, name] : subdomain_map)
536 subdomain_ids.push_back(
id);
537 subdomain_names.push_back(name);
540 io.
data(n_subdomain_names,
"# subdomain id to name map");
542 if (n_subdomain_names)
544 io.
data(subdomain_ids);
545 io.
data(subdomain_names);
557 io.
data(n_nodes_here,
"# n_nodes on proc");
560 const unsigned int n_extra_integers =
564 std::vector<largest_id_type> id_pid(2 + n_extra_integers);
567 std::vector<Real> coords(LIBMESH_DIM);
569 for (
const auto & node : nodeset)
571 id_pid[0] = node->id();
572 id_pid[1] = node->processor_id();
574 libmesh_assert_equal_to(n_extra_integers, node->n_extra_integers());
575 for (
unsigned int i=0; i != n_extra_integers; ++i)
576 id_pid[2+i] = node->get_extra_integer(i);
578 io.
data_stream(id_pid.data(), 2 + n_extra_integers, 2 + n_extra_integers);
580#ifdef LIBMESH_ENABLE_UNIQUE_ID
583 io.
data(unique_id,
"# unique id");
586 coords[0] = (*node)(0);
589 coords[1] = (*node)(1);
593 coords[2] = (*node)(2);
603 const std::set<const Elem *, CompareElemIdsByLevel> & elements)
const
609 const unsigned int n_extra_integers =
614 std::vector<largest_id_type> elem_data(6 + n_extra_integers);
615 std::vector<largest_id_type> conn_data;
616 std::vector<largest_id_type> runtime_topology;
620 io.
data(n_elems_here,
"# number of elements");
622 for (
const auto & elem : elements)
624 unsigned int n_nodes = elem->n_nodes();
626 elem_data[0] = elem->id();
627 elem_data[1] = elem->type();
628 elem_data[2] = elem->processor_id();
629 elem_data[3] = elem->subdomain_id();
631#ifdef LIBMESH_ENABLE_AMR
632 if (elem->parent() !=
nullptr)
634 elem_data[4] = elem->parent()->id();
635 elem_data[5] = elem->parent()->which_child_am_i(elem);
644 for (
unsigned int i=0; i != n_extra_integers; ++i)
645 elem_data[6+i] = elem->get_extra_integer(i);
649 for (
unsigned int i=0; i<
n_nodes; i++)
650 conn_data[i] = elem->node_id(i);
653 cast_int<unsigned int>(elem_data.size()),
654 cast_int<unsigned int>(elem_data.size()));
656#ifdef LIBMESH_ENABLE_UNIQUE_ID
659 io.
data(unique_id,
"# unique id");
662#ifdef LIBMESH_ENABLE_AMR
663 uint16_t p_level = cast_int<uint16_t>(elem->p_level());
664 io.
data(p_level,
"# p_level");
666 uint16_t rflag = elem->refinement_flag();
667 io.
data(rflag,
"# rflag");
669 uint16_t pflag = elem->p_refinement_flag();
670 io.
data(pflag,
"# pflag");
673 if (elem->runtime_topology())
676 (!write_runtime_topology,
677 "Checkpoint format 1.6 or newer is required to write " <<
680 runtime_topology.clear();
681 runtime_topology.push_back(
n_nodes);
682 runtime_topology.push_back(elem->n_sides());
683 for (
auto s : elem->side_index_range())
685 const auto side_nodes = elem->nodes_on_side(s);
686 runtime_topology.push_back(side_nodes.size());
687 for (
const auto n : side_nodes)
688 runtime_topology.push_back(n);
691 io.
data(runtime_topology,
"# runtime topology");
695 cast_int<unsigned int>(conn_data.size()),
696 cast_int<unsigned int>(conn_data.size()));
702 const std::set<const Elem *, CompareElemIdsByLevel> & elements)
const
707 std::vector<largest_id_type> elem_ids, parent_ids;
708 std::vector<uint16_t> elem_sides, child_numbers;
710 for (
const auto & elem : elements)
712 for (
auto n : elem->side_index_range())
716 (neigh && !elements.count(neigh)))
718 elem_ids.push_back(elem->id());
719 elem_sides.push_back(n);
723#ifdef LIBMESH_ENABLE_AMR
724 if (elem->has_children())
726 for (
unsigned short c = 0,
727 nc = cast_int<unsigned short>(elem->n_children());
732 (child && !elements.count(child)))
734 parent_ids.push_back(elem->id());
735 child_numbers.push_back(c);
742 io.
data(elem_ids,
"# remote neighbor elem_ids");
743 io.
data(elem_sides,
"# remote neighbor elem_sides");
744 io.
data(parent_ids,
"# remote child parent_ids");
745 io.
data(child_numbers,
"# remote child_numbers");
751 const std::set<const Elem *, CompareElemIdsByLevel> & elements,
752 const std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> & bc_triples)
const
757 std::size_t bc_size = bc_triples.size();
759 std::vector<largest_id_type> element_id_list;
760 std::vector<uint16_t> side_list;
761 std::vector<largest_id_type> bc_id_list;
763 element_id_list.reserve(bc_size);
764 side_list.reserve(bc_size);
765 bc_id_list.reserve(bc_size);
767 std::unordered_set<dof_id_type> elems;
768 for (
auto & e : elements)
769 elems.insert(e->id());
771 for (
const auto & t : bc_triples)
772 if (elems.count(std::get<0>(t)))
774 element_id_list.push_back(std::get<0>(t));
775 side_list.push_back(std::get<1>(t));
776 bc_id_list.push_back(std::get<2>(t));
780 io.
data(element_id_list,
"# element ids for bcs");
781 io.
data(side_list,
"# sides of elements for bcs");
782 io.
data(bc_id_list,
"# bc ids");
789 const std::vector<std::tuple<dof_id_type, boundary_id_type>> & bc_tuples)
const
797 std::size_t nodeset_size = bc_tuples.size();
799 std::vector<largest_id_type> node_id_list;
800 std::vector<largest_id_type> bc_id_list;
802 node_id_list.reserve(nodeset_size);
803 bc_id_list.reserve(nodeset_size);
805 for (
const auto & t : bc_tuples)
808 node_id_list.push_back(std::get<0>(t));
809 bc_id_list.push_back(std::get<1>(t));
812 io.
data(node_id_list,
"# node id list");
813 io.
data(bc_id_list,
"# nodeset bc id list");
820 const std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
821 info.get_sideset_name_map() : info.get_nodeset_name_map();
823 std::vector<largest_id_type> boundary_ids; boundary_ids.reserve(boundary_map.size());
824 std::vector<std::string> boundary_names; boundary_names.reserve(boundary_map.size());
830 for (
const auto & [
id, name] : boundary_map)
834 boundary_ids.push_back(
id);
835 boundary_names.push_back(name);
839 io.
data(n_boundary_names,
"# sideset id to name map");
841 io.
data(n_boundary_names,
"# nodeset id to name map");
843 if (n_boundary_names)
845 io.
data(boundary_ids);
846 io.
data(boundary_names);
852 LOG_SCOPE(
"read()",
"CheckpointIO");
860 auto header_name = header_file(input_name, input_n_procs);
861 bool input_parallel = input_n_procs > 0;
880 proc_id = cast_int<processor_id_type>(proc_id + stride))
882 auto file_name = split_file(input_name, input_n_procs, proc_id);
885 std::ifstream in (file_name.c_str());
887 libmesh_error_msg_if(!in.good(),
"ERROR: cannot locate specified file:\n\t" << file_name);
893 const bool expect_all_remote =
901 this->read_subfile<uint16_t>(io, expect_all_remote);
904 this->read_subfile<uint32_t>(io, expect_all_remote);
907 this->read_subfile<uint64_t>(io, expect_all_remote);
936template <
typename file_
id_type>
942 uint16_t mesh_dimension;
945 uint16_t input_parallel;
946 file_id_type input_n_procs;
948 std::string input_version;
949 std::vector<std::string> node_integer_names, elem_integer_names;
957 io.
data(input_version);
964 io.
data (mesh_dimension);
967 io.
data(input_parallel);
971 io.
data(input_n_procs);
974 this->read_subdomain_names<file_id_type>(io);
979 this->read_bc_names<file_id_type>(io, boundary_info,
true);
980 this->read_bc_names<file_id_type>(io, boundary_info,
false);
983 std::swap(input_version, this->
version());
985 std::swap(input_version, this->
version());
987 if (read_extra_integers)
988 this->read_integers_names<file_id_type>
989 (io, node_integer_names, elem_integer_names);
994 this->
version() = input_version;
1006 std::map<subdomain_id_type, std::string> & subdomain_map =
1017 for (
auto & int_name : node_integer_names)
1020 for (
auto & int_name : elem_integer_names)
1023 return input_parallel ? input_n_procs : 0;
1028template <
typename file_
id_type>
1032 this->read_nodes<file_id_type> (io);
1035 this->read_connectivity<file_id_type> (io);
1038 this->read_remote_elem<file_id_type> (io, expect_all_remote);
1041 this->read_bcs<file_id_type> (io);
1044 this->read_nodesets<file_id_type> (io);
1049template <
typename file_
id_type>
1054 std::map<subdomain_id_type, std::string> & subdomain_map =
1057 std::vector<file_id_type> subdomain_ids;
1058 subdomain_ids.reserve(subdomain_map.size());
1060 std::vector<std::string> subdomain_names;
1061 subdomain_names.reserve(subdomain_map.size());
1063 file_id_type n_subdomain_names = 0;
1064 io.
data(n_subdomain_names,
"# subdomain id to name map");
1066 if (n_subdomain_names)
1068 io.
data(subdomain_ids);
1069 io.
data(subdomain_names);
1072 subdomain_map[cast_int<subdomain_id_type>(subdomain_ids[i])] =
1079template <
typename file_
id_type>
1085 file_id_type n_nodes_here;
1086 io.
data(n_nodes_here,
"# n_nodes on proc");
1090 const unsigned int n_extra_integers =
1094 std::vector<file_id_type> id_pid(2 + n_extra_integers);
1097 std::vector<Real> coords(LIBMESH_DIM);
1099 for (
unsigned int i=0; i<n_nodes_here; i++)
1101 io.
data_stream(id_pid.data(), 2 + n_extra_integers, 2 + n_extra_integers);
1103#ifdef LIBMESH_ENABLE_UNIQUE_ID
1104 file_id_type unique_id = 0;
1105 io.
data(unique_id,
"# unique id");
1108 io.
data_stream(coords.data(), LIBMESH_DIM, LIBMESH_DIM);
1121 const dof_id_type id = cast_int<dof_id_type>(id_pid[0]);
1136 libmesh_assert_equal_to(pid, old_node->
processor_id());
1140 for (
unsigned int ei=0; ei != n_extra_integers; ++ei)
1142 const dof_id_type extra_int = cast_int<dof_id_type>(id_pid[2+ei]);
1147#ifdef LIBMESH_ENABLE_UNIQUE_ID
1148 libmesh_assert_equal_to(unique_id, old_node->
unique_id());
1156#ifdef LIBMESH_ENABLE_UNIQUE_ID
1162 for (
unsigned int ei=0; ei != n_extra_integers; ++ei)
1164 const dof_id_type extra_int = cast_int<dof_id_type>(id_pid[2+ei]);
1173template <
typename file_
id_type>
1182 const unsigned int n_extra_integers =
1185 file_id_type n_elems_here;
1186 io.
data(n_elems_here);
1194 bool file_is_broken =
false;
1196 for (
unsigned int i=0; i<n_elems_here; i++)
1199 std::vector<file_id_type> elem_data(6 + n_extra_integers);
1201 (elem_data.data(), cast_int<unsigned int>(elem_data.size()),
1202 cast_int<unsigned int>(elem_data.size()));
1204#ifdef LIBMESH_ENABLE_UNIQUE_ID
1205 file_id_type unique_id = 0;
1206 io.
data(unique_id,
"# unique id");
1209#ifdef LIBMESH_ENABLE_AMR
1210 uint16_t p_level = 0;
1211 io.
data(p_level,
"# p_level");
1213 uint16_t rflag, pflag;
1214 io.
data(rflag,
"# rflag");
1215 io.
data(pflag,
"# pflag");
1219 static_cast<ElemType>(elem_data[1]);
1220 const bool is_c0polygon = (elem_type ==
C0POLYGON);
1221 const bool is_c0polyhedron = (elem_type ==
C0POLYHEDRON);
1226 std::vector<std::vector<unsigned int>> nodes_on_sides;
1228 if (has_runtime_topology)
1230 libmesh_error_msg_if
1231 (!read_runtime_topology,
1232 "Checkpoint format 1.6 or newer is required to read " <<
1235 std::vector<file_id_type> runtime_topology;
1236 io.
data(runtime_topology,
"# runtime topology");
1237 libmesh_error_msg_if(runtime_topology.size() < 2,
1238 "Invalid runtime element topology.");
1240 std::size_t topology_index = 0;
1242 cast_int<unsigned int>(runtime_topology[topology_index++]);
1243 const unsigned int n_sides =
1244 cast_int<unsigned int>(runtime_topology[topology_index++]);
1245 nodes_on_sides.resize(n_sides);
1249 libmesh_error_msg_if
1250 (topology_index == runtime_topology.size(),
1251 "Incomplete runtime element checkpoint topology.");
1253 const unsigned int n_side_nodes =
1254 cast_int<unsigned int>(runtime_topology[topology_index++]);
1255 libmesh_error_msg_if
1256 (n_side_nodes > runtime_topology.size() - topology_index,
1257 "Invalid runtime element side checkpoint topology.");
1259 auto & side_nodes = nodes_on_sides[s];
1260 side_nodes.resize(n_side_nodes);
1263 const unsigned int local_node =
1264 cast_int<unsigned int>(runtime_topology[topology_index++]);
1265 libmesh_error_msg_if
1267 "Runtime element side checkpoint topology references "
1268 "an invalid local node.");
1269 side_nodes[n] = local_node;
1273 libmesh_error_msg_if
1274 (topology_index != runtime_topology.size(),
1275 "Extra data in runtime element checkpoint topology.");
1279 libmesh_error_msg_if
1281 "Invalid C0POLYGON checkpoint topology.");
1282 for (
const auto & side_nodes : nodes_on_sides)
1283 libmesh_error_msg_if
1284 (side_nodes.size() != 2,
1285 "Invalid C0POLYGON side checkpoint topology.");
1287 else if (is_c0polyhedron)
1289 libmesh_error_msg_if(n_sides < 4,
1290 "Invalid C0POLYHEDRON checkpoint topology.");
1291 for (
const auto & side_nodes : nodes_on_sides)
1292 libmesh_error_msg_if
1293 (side_nodes.size() < 3,
1294 "Invalid C0POLYHEDRON side checkpoint topology.");
1299 std::vector<file_id_type> conn_data(
n_nodes);
1301 (conn_data.data(), cast_int<unsigned int>(conn_data.size()),
1302 cast_int<unsigned int>(conn_data.size()));
1305 cast_int<dof_id_type> (elem_data[0]);
1307 cast_int<processor_id_type>
1310 restrict_int<subdomain_id_type>(elem_data[3]);
1314 if (i == 0 && elem_data[4] == 65535)
1315 file_is_broken =
true;
1322 (file_is_broken && elem_data[4] == 65535)) ?
1323 nullptr :
mesh.
elem_ptr(cast_int<dof_id_type>(elem_data[4]));
1325 const unsigned short int child_num =
1327 (file_is_broken && elem_data[5] == 65535)) ?
1328 static_cast<unsigned short>(-1) :
1329 cast_int<unsigned short>(elem_data[5]);
1332 libmesh_assert_equal_to
1333 (child_num,
static_cast<unsigned short>(-1));
1345 libmesh_assert_equal_to(elem_type, old_elem->
type());
1346 libmesh_assert_equal_to(proc_id, old_elem->
processor_id());
1347 libmesh_assert_equal_to(subdomain_id, old_elem->
subdomain_id());
1349 libmesh_assert_equal_to(parent, old_elem->
parent());
1355 for (
unsigned int ei=0; ei != n_extra_integers; ++ei)
1357 const dof_id_type extra_int = cast_int<dof_id_type>(elem_data[6+ei]);
1362 libmesh_assert_equal_to(old_elem->
n_nodes(), conn_data.size());
1364 for (
unsigned int n=0,
1365 n_conn = cast_int<unsigned int>(conn_data.size());
1367 libmesh_assert_equal_to
1369 cast_int<dof_id_type>(conn_data[n]));
1371 if (has_runtime_topology)
1373 libmesh_assert_equal_to(old_elem->
n_sides(),
1374 nodes_on_sides.size());
1385 std::unique_ptr<Elem> elem;
1386 std::unique_ptr<Node> generated_mid_elem_node;
1389 elem = std::make_unique<C0Polygon>(
n_nodes, parent);
1390 else if (is_c0polyhedron)
1392 std::vector<std::shared_ptr<Polygon>> sides(nodes_on_sides.size());
1395 const auto & side_node_indices = nodes_on_sides[s];
1397 std::make_shared<C0Polygon>
1398 (cast_int<unsigned int>(side_node_indices.size()));
1402 (conn_data[side_node_indices[n]])));
1403 sides[s] = std::move(side);
1406 elem = std::make_unique<C0Polyhedron>
1407 (sides, generated_mid_elem_node, parent);
1409 libmesh_error_msg_if
1410 (elem->n_nodes() != conn_data.size(),
1411 "C0POLYHEDRON checkpoint topology is incompatible with "
1412 "this libMesh configuration.");
1414 for (
auto n :
make_range(elem->n_vertices()))
1415 libmesh_error_msg_if
1416 (elem->node_id(n) !=
1417 cast_int<dof_id_type>(conn_data[n]),
1418 "C0POLYHEDRON checkpoint topology has inconsistent "
1419 "local node ordering.");
1424 if (has_runtime_topology)
1426 libmesh_error_msg_if
1427 (!elem->runtime_topology() ||
1428 elem->n_nodes() != conn_data.size() ||
1429 elem->n_sides() != nodes_on_sides.size(),
1431 " checkpoint topology is incompatible with this "
1432 "libMesh configuration.");
1435 libmesh_error_msg_if
1436 (elem->nodes_on_side(s) != nodes_on_sides[s],
1438 " checkpoint topology has inconsistent side ordering.");
1441#ifdef LIBMESH_ENABLE_UNIQUE_ID
1442 elem->set_unique_id(unique_id);
1445 if (elem->dim() > highest_elem_dim)
1446 highest_elem_dim = elem->dim();
1448 elem->set_id() = id;
1449 elem->processor_id() = proc_id;
1450 elem->subdomain_id() = subdomain_id;
1452#ifdef LIBMESH_ENABLE_AMR
1453 elem->hack_p_level(p_level);
1455 elem->set_refinement_flag (cast_int<Elem::RefinementState>(rflag));
1456 elem->set_p_refinement_flag(cast_int<Elem::RefinementState>(pflag));
1463 parent->
add_child(elem.get(), child_num);
1472 for (
unsigned int n=0,
1473 n_conn = cast_int<unsigned int>(conn_data.size());
1481 for (
unsigned int ei=0; ei != n_extra_integers; ++ei)
1483 const dof_id_type extra_int = cast_int<dof_id_type>(elem_data[6+ei]);
1493template <
typename file_
id_type>
1500 std::vector<file_id_type> elem_ids;
1501 std::vector<uint16_t> elem_sides;
1503 io.
data(elem_ids,
"# remote neighbor elem_ids");
1504 io.
data(elem_sides,
"# remote neighbor elem_sides");
1506 libmesh_assert_equal_to(elem_ids.size(), elem_sides.size());
1519 std::vector<file_id_type> parent_ids;
1520 std::vector<uint16_t> child_numbers;
1522 io.
data(parent_ids,
"# remote child parent_ids");
1523 io.
data(child_numbers,
"# remote child_numbers");
1525#ifdef LIBMESH_ENABLE_AMR
1547template <
typename file_
id_type>
1556 std::vector<file_id_type> element_id_list;
1557 std::vector<uint16_t> side_list;
1558 std::vector<file_id_type> bc_id_list;
1560 io.
data(element_id_list,
"# element ids for bcs");
1561 io.
data(side_list,
"# sides of elements for bcs");
1562 io.
data(bc_id_list,
"# bc ids");
1566 (cast_int<dof_id_type>(element_id_list[i]), side_list[i],
1567 cast_int<boundary_id_type>(bc_id_list[i]));
1572template <
typename file_
id_type>
1581 std::vector<file_id_type> node_id_list;
1582 std::vector<file_id_type> bc_id_list;
1584 io.
data(node_id_list,
"# node id list");
1585 io.
data(bc_id_list,
"# nodeset bc id list");
1589 (cast_int<dof_id_type>(node_id_list[i]),
1590 cast_int<boundary_id_type>(bc_id_list[i]));
1595template <
typename file_
id_type>
1598 std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
1599 info.set_sideset_name_map() : info.set_nodeset_name_map();
1601 std::vector<file_id_type> boundary_ids;
1602 std::vector<std::string> boundary_names;
1604 file_id_type n_boundary_names = 0;
1607 io.
data(n_boundary_names,
"# sideset id to name map");
1609 io.
data(n_boundary_names,
"# nodeset id to name map");
1611 if (n_boundary_names)
1613 io.
data(boundary_ids);
1614 io.
data(boundary_names);
1619 boundary_map[cast_int<boundary_id_type>(boundary_ids[i])] =
1624template <
typename file_
id_type>
1627 std::vector<std::string> & node_integer_names,
1628 std::vector<std::string> & elem_integer_names)
1630 file_id_type n_node_integers, n_elem_integers;
1632 io.
data(n_node_integers,
"# n_extra_integers per node");
1633 io.
data(node_integer_names);
1634 io.
data(n_elem_integers,
"# n_extra_integers per elem");
1635 io.
data(elem_integer_names);
1642 unsigned int max_level = 0;
1644 for (
const auto & elem :
as_range(begin, end))
1645 max_level = std::max(elem->level(), max_level);
1647 return max_level + 1;
processor_id_type size() const
processor_id_type rank() const
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
std::map< boundary_id_type, std::string > & set_sideset_name_map()
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure.
std::map< boundary_id_type, std::string > & set_nodeset_name_map()
void read_nodes(Xdr &io)
Read the nodal locations for a parallel, distributed mesh.
processor_id_type _my_n_processors
void write_bc_names(Xdr &io, const BoundaryInfo &info, bool is_sideset) const
Write boundary names information (sideset and nodeset)
file_id_type read_header(const std::string &name)
Read header data on processor 0, then broadcast.
void write_nodesets(Xdr &io, const connected_node_set_type &nodeset, const std::vector< std::tuple< dof_id_type, boundary_id_type > > &bc_tuples) const
Write the nodal boundary conditions for part of a mesh.
void read_subdomain_names(Xdr &io)
Read subdomain name information.
CheckpointIO(MeshBase &, const bool=false)
Constructor.
processor_id_type select_split_config(const std::string &input_name, header_id_type &data_size)
void write_connectivity(Xdr &io, const std::set< const Elem *, CompareElemIdsByLevel > &elements) const
Write the connectivity for part of a mesh.
bool version_at_least_1_6() const
virtual ~CheckpointIO()
Destructor.
void write_subdomain_names(Xdr &io) const
Write subdomain name information.
void read_connectivity(Xdr &io)
Read the connectivity for a parallel, distributed mesh.
void write_nodes(Xdr &io, const connected_node_set_type &nodeset) const
Write the nodal locations for part of a mesh.
void read_bcs(Xdr &io)
Read the boundary conditions for a parallel, distributed mesh.
void read_remote_elem(Xdr &io, bool expect_all_remote)
Read the remote_elem neighbor and child links for a parallel, distributed mesh.
void read_bc_names(Xdr &io, BoundaryInfo &info, bool is_sideset)
Read boundary names information (sideset and nodeset)
std::vector< processor_id_type > _my_processor_ids
void write_remote_elem(Xdr &io, const std::set< const Elem *, CompareElemIdsByLevel > &elements) const
Write the remote_elem neighbor and child links for part of a mesh.
void read_integers_names(Xdr &io, std::vector< std::string > &node_integer_names, std::vector< std::string > &elem_integer_names)
Read extra integers names information.
void read_nodesets(Xdr &io)
Read the nodeset conditions for a parallel, distributed mesh.
virtual void read(const std::string &input_name) override
This method implements reading a mesh from a specified file.
bool binary() const
Get/Set the flag indicating if we should read/write binary.
static void cleanup(const std::string &input_name, processor_id_type n_procs)
Used to remove a checkpoint directory and its corresponding files.
const std::string & version() const
Get/Set the version string.
virtual void write(const std::string &name) override
This method implements writing a mesh to a specified file.
void read_subfile(Xdr &io, bool expect_all_remote)
Read a non-header file.
void write_bcs(Xdr &io, const std::set< const Elem *, CompareElemIdsByLevel > &elements, const std::vector< std::tuple< dof_id_type, unsigned short int, boundary_id_type > > &bc_triples) const
Write the side boundary conditions for part of a mesh.
bool parallel() const
Get/Set the flag indicating if we should read/write binary.
bool version_at_least_1_5() const
unsigned int n_active_levels_in(MeshBase::const_element_iterator begin, MeshBase::const_element_iterator end) const
dof_id_type get_extra_integer(const unsigned int index) const
Gets the value on this object of the extra integer associated with index, which should have been obta...
unsigned int n_extra_integers() const
Returns how many extra integers are associated to the DofObject.
processor_id_type processor_id() const
unique_id_type unique_id() const
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
void set_extra_integer(const unsigned int index, const dof_id_type value)
Sets the value on this object of the extra integer associated with index, which should have been obta...
This is the base class from which all geometric element types are derived.
const Elem * raw_child_ptr(unsigned int i) const
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
virtual unsigned int n_nodes() const =0
const Elem * parent() const
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
const Elem * child_ptr(unsigned int i) const
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
subdomain_id_type subdomain_id() const
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
virtual ElemType type() const =0
virtual unsigned int n_sides() const =0
dof_id_type node_id(const unsigned int i) const
const Elem * neighbor_ptr(unsigned int i) const
This is the MeshBase class.
virtual bool is_serial() const
unsigned int n_elem_integers() const
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
virtual const Node * node_ptr(const dof_id_type i) const =0
unsigned int mesh_dimension() const
virtual dof_id_type n_elem() const =0
virtual bool is_replicated() const
unsigned int recalculate_n_partitions()
In a few (very rare) cases, the user may have manually tagged the elements with specific processor ID...
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
unsigned int add_node_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
Register an integer datum (of type dof_id_type) to be added to each node in the mesh.
const std::string & get_node_integer_name(unsigned int i) const
virtual const Node * query_node_ptr(const dof_id_type i) const =0
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual void update_post_partitioning()
Recalculate any cached data (or invalidate any caches that are computed on the fly) after elements an...
virtual const Elem * elem_ptr(const dof_id_type i) const =0
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
Register an integer datum (of type dof_id_type) to be added to each element in the mesh.
const std::string & get_elem_integer_name(unsigned int i) const
virtual void set_distributed()
Asserts that not all elements and nodes of the mesh necessarily exist on the current processor.
unsigned int n_node_integers() const
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
virtual const Elem & elem_ref(const dof_id_type i) const
std::map< subdomain_id_type, std::string > & set_subdomain_name_map()
virtual void partition(const unsigned int n_parts)
Call the default partitioner (currently metis_partition()).
void skip_partitioning(bool skip)
If true is passed in then nothing on this mesh will be (re)partitioned.
This is the MeshCommunication class.
void broadcast(MeshBase &) const
This method takes a mesh (which is assumed to reside on processor 0) and broadcasts it to all the oth...
This class defines an abstract interface for Mesh output.
A Node is like a Point, but with more information.
An object whose state is distributed along a set of processors.
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
In parallel meshes where a ghost element has neighbors which do not exist on the local processor,...
This class implements a C++ interface to the XDR (eXternal Data Representation) format.
void data_stream(T *val, const unsigned int len, const unsigned int line_break=libMesh::invalid_uint)
Inputs or outputs a raw data stream.
void close()
Closes the file if it is open.
void data(T &a, std::string_view comment="")
Inputs or outputs a single value.
int mkdir(const char *pathname)
Create a directory.
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
void query_ghosting_functors(const MeshBase &mesh, processor_id_type pid, MeshBase::const_element_iterator elem_it, MeshBase::const_element_iterator elem_end, connected_elem_set_type &connected_elements)
ElemType
Defines an enum for geometric element types.
void libmesh_ignore(const Args &...)
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
std::unique_ptr< CheckpointIO > split_mesh(MeshBase &mesh, processor_id_type nsplits)
split_mesh takes the given initialized/opened mesh and partitions it into nsplits pieces or chunks.
const RemoteElem * remote_elem
std::set< const Node * > connected_node_set_type
void connect_element_dependencies(const MeshBase &mesh, connected_elem_set_type &connected_elements, connected_node_set_type &connected_nodes)
void connect_children(const MeshBase &mesh, MeshBase::const_element_iterator elem_it, MeshBase::const_element_iterator elem_end, connected_elem_set_type &connected_elements)
uint8_t processor_id_type
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
The definition of the const_element_iterator struct.
Used to iterate over non-nullptr, active entries in a container.
Used to iterate over non-nullptr entries in a container.
const dof_id_type n_nodes