21 #include "libmesh/xdr_io.h" 22 #include "libmesh/boundary_info.h" 23 #include "libmesh/elem.h" 24 #include "libmesh/enum_xdr_mode.h" 25 #include "libmesh/int_range.h" 26 #include "libmesh/libmesh_logging.h" 27 #include "libmesh/mesh_base.h" 28 #include "libmesh/mesh_tools.h" 29 #include "libmesh/node.h" 30 #include "libmesh/partitioner.h" 31 #include "libmesh/utility.h" 32 #include "libmesh/xdr_cxx.h" 53 template <
class T,
class U>
54 struct libmesh_type_is_same {
55 static const bool value =
false;
59 struct libmesh_type_is_same<T, T> {
60 static const bool value =
true;
81 _write_serial (false),
82 _write_parallel (false),
83 #ifdef LIBMESH_ENABLE_UNIQUE_ID
84 _write_unique_id (true),
86 _write_unique_id (false),
89 _version (
"libMesh-1.8.0"),
90 _bc_file_name (
"n/a"),
91 _partition_map_file (
"n/a"),
92 _subdomain_map_file (
"n/a"),
105 _write_serial (false),
106 _write_parallel (false),
107 #ifdef LIBMESH_ENABLE_UNIQUE_ID
108 _write_unique_id (true),
110 _write_unique_id (false),
113 _version (
"libMesh-1.8.0"),
114 _bc_file_name (
"n/a"),
115 _partition_map_file (
"n/a"),
116 _subdomain_map_file (
"n/a"),
117 _p_level_file (
"n/a")
129 libmesh_error_msg_if(this->
legacy(),
"We don't support writing parallel files in the legacy format.");
133 LOG_SCOPE(
"write()",
"XdrIO");
158 if ((n_side_bcs || n_edge_bcs || n_shellface_bcs || n_nodesets) &&
172 if ((n_p_levels > 1) &&
179 std::string full_ver = this->
version() + (write_parallel_files ?
" parallel" :
"");
183 io.
data (max_node_id,
"# number of nodes");
199 io.
data (write_size,
"# type size");
201 io.
data (write_partitioning ? write_size : zero_size,
"# pid size");
202 io.
data (write_subdomain_id ? write_size : zero_size,
"# sid size");
203 io.
data (write_p_level ? write_size : zero_size,
"# p-level size");
205 io.
data (write_bcs ? write_size : zero_size,
"# eid size");
206 io.
data (write_bcs ? write_size : zero_size,
"# side size");
207 io.
data (write_bcs ? write_size : zero_size,
"# bid size");
211 io.
data((n_elem_integers || n_node_integers) ? write_size : zero_size,
"# extra integer size");
214 std::vector<std::string> node_integer_names;
215 for (
unsigned int i=0; i != n_node_integers; ++i)
217 io.
data(node_integer_names,
"# node integer names");
220 std::vector<std::string> elem_integer_names;
221 for (
unsigned int i=0; i != n_elem_integers; ++i)
223 io.
data(elem_integer_names,
"# elem integer names");
228 io.
data(elemset_codes,
"# elemset codes");
232 for (
const auto & elemset_code : elemset_codes)
237 std::vector<dof_id_type> elemset_id_vec(id_set_to_fill.begin(), id_set_to_fill.end());
240 std::string comment_string =
"# elemset ids for elemset code " + std::to_string(elemset_code);
241 io.
data(elemset_id_vec, comment_string);
245 if (write_parallel_files)
249 libMesh::out <<
"Warning! Parallel xda/xdr is not yet implemented.\n";
250 libMesh::out <<
"Writing a serialized file instead." << std::endl;
315 std::vector<new_header_id_type> subdomain_ids;
316 subdomain_ids.reserve(subdomain_map.size());
318 std::vector<std::string> subdomain_names;
319 subdomain_names.reserve(subdomain_map.size());
325 for (
const auto & [sbd_id,
name] : subdomain_map)
329 subdomain_ids.push_back(sbd_id);
330 subdomain_names.push_back(
name);
333 io.
data(n_subdomain_names,
"# subdomain id to name map");
335 if (n_subdomain_names)
337 io.
data(subdomain_ids);
338 io.
data(subdomain_names);
371 n_global_elem_at_level[level] =
373 mesh.local_level_elements_end(level));
375 this->
comm().
sum(n_global_elem_at_level[level]);
377 tot_n_elem += n_global_elem_at_level[level];
379 libmesh_assert_less_equal (n_global_elem_at_level[level],
n_elem);
380 libmesh_assert_less_equal (tot_n_elem,
n_elem);
383 std::vector<xdr_id_type>
384 xfer_conn, recv_conn;
385 std::vector<dof_id_type>
387 std::vector<xdr_id_type> output_buffer;
388 std::vector<std::size_t>
391 #ifdef LIBMESH_ENABLE_AMR 392 typedef std::map<dof_id_type, std::pair<processor_id_type, dof_id_type>> id_map_type;
393 id_map_type parent_id_map, child_id_map;
400 for (
const auto & elem :
as_range(
mesh.local_level_elements_begin(0),
401 mesh.local_level_elements_end(0)))
407 #ifdef LIBMESH_ENABLE_AMR 408 parent_id_map[elem->id()] = std::make_pair(this->
processor_id(),
413 xfer_conn.push_back(my_next_elem);
415 std::size_t my_size = xfer_conn.size();
416 this->
comm().
gather (0, my_next_elem, n_elem_on_proc);
417 this->
comm().
gather (0, my_size, xfer_buf_sizes);
419 processor_offsets[0] = 0;
421 processor_offsets[pid] = processor_offsets[pid-1] + n_elem_on_proc[pid-1];
429 std::string comment =
"# n_elem at level 0", legend =
", [ type ";
432 if (write_partitioning)
434 if (write_subdomain_id)
437 legend +=
"p_level ";
438 legend +=
"(n0 ... nN-1) ]";
440 io.
data (n_global_elem_at_level[0], comment);
445 recv_conn.resize(xfer_buf_sizes[pid]);
447 recv_conn = xfer_conn;
455 for (
auto [elem, recv_conn_iter, n_elem_received] =
456 std::tuple{
xdr_id_type(0), recv_conn.begin(), recv_conn.back()};
457 elem<n_elem_received; elem++, next_global_elem++)
459 output_buffer.clear();
465 output_buffer.push_back(*recv_conn_iter++);
470 output_buffer.push_back(tmp);
473 tmp = *recv_conn_iter++;
474 if (write_partitioning)
475 output_buffer.push_back(tmp);
478 tmp = *recv_conn_iter++;
479 if (write_subdomain_id)
480 output_buffer.push_back(tmp);
482 #ifdef LIBMESH_ENABLE_AMR 484 tmp = *recv_conn_iter++;
486 output_buffer.push_back(tmp);
490 output_buffer.push_back(*recv_conn_iter++);
494 output_buffer.push_back(*recv_conn_iter++);
497 (output_buffer.data(),
498 cast_int<unsigned int>(output_buffer.size()),
499 cast_int<unsigned int>(output_buffer.size()));
506 #ifdef LIBMESH_ENABLE_AMR 516 for (
const auto & parent :
as_range(
mesh.local_level_elements_begin(level-1),
517 mesh.local_level_elements_end(level-1)))
518 if (!parent->active())
520 id_map_type::iterator pos = parent_id_map.find(parent->id());
524 parent_id_map.erase(pos);
526 for (
auto & child : parent->child_ref_range())
528 pack_element (xfer_conn, &child, parent_id, parent_pid, n_elem_integers);
533 child_id_map[child.id()] = std::make_pair (child.processor_id(),
534 my_n_elem_written_at_level++);
538 xfer_conn.push_back(my_n_elem_written_at_level);
539 my_size = xfer_conn.size();
540 this->
comm().
gather (0, my_size, xfer_buf_sizes);
547 std::ostringstream buf;
548 buf <<
"# n_elem at level " << level <<
", [ type ";
553 if (write_partitioning)
555 if (write_subdomain_id)
559 buf <<
"(n0 ... nN-1) ]";
561 io.
data (n_global_elem_at_level[level], buf.str());
566 recv_conn.resize(xfer_buf_sizes[pid]);
568 recv_conn = xfer_conn;
576 for (
auto [elem, recv_conn_iter, n_elem_received] =
577 std::tuple{
xdr_id_type(0), recv_conn.begin(), recv_conn.back()};
578 elem<n_elem_received;
579 elem++, next_global_elem++)
581 output_buffer.clear();
587 output_buffer.push_back(*recv_conn_iter++);
592 output_buffer.push_back(tmp);
595 const xdr_id_type parent_local_id = *recv_conn_iter++;
600 output_buffer.push_back (parent_local_id+processor_offsets[parent_pid]);
603 tmp = *recv_conn_iter++;
604 if (write_partitioning)
605 output_buffer.push_back(tmp);
608 tmp = *recv_conn_iter++;
609 if (write_subdomain_id)
610 output_buffer.push_back(tmp);
613 tmp = *recv_conn_iter++;
615 output_buffer.push_back(tmp);
619 output_buffer.push_back(*recv_conn_iter++);
623 output_buffer.push_back(*recv_conn_iter++);
626 (output_buffer.data(),
627 cast_int<unsigned int>(output_buffer.size()),
628 cast_int<unsigned int>(output_buffer.size()));
636 processor_offsets[0] = processor_offsets.back() + n_elem_on_proc.back();
637 this->
comm().
gather (0, my_n_elem_written_at_level, n_elem_on_proc);
639 processor_offsets[pid] = processor_offsets[pid-1] + n_elem_on_proc[pid-1];
645 std::map<processor_id_type, std::vector<dof_id_type>> requested_ids;
647 for (
const auto & elem :
as_range(
mesh.local_level_elements_begin(level),
648 mesh.local_level_elements_end(level)))
649 if (!child_id_map.count(elem->id()))
651 libmesh_assert_not_equal_to (elem->parent()->processor_id(), this->
processor_id());
654 requested_ids[pid].push_back(elem->id());
657 auto gather_functor =
660 const std::vector<dof_id_type> & ids,
661 std::vector<dof_id_type> & data)
663 const std::size_t ids_size = ids.size();
664 data.resize(ids_size);
667 for (std::size_t i=0; i != ids_size; i++)
670 libmesh_assert_equal_to (child_id_map[ids[i]].first, pid);
672 data[i] = child_id_map[ids[i]].second;
676 auto action_functor =
679 const std::vector<dof_id_type> & ids,
680 const std::vector<dof_id_type> & data)
682 std::size_t data_size = data.size();
684 for (std::size_t i=0; i != data_size; i++)
685 child_id_map[ids[i]] =
686 std::make_pair (pid, data[i]);
691 Parallel::pull_parallel_vector_data
692 (this->
comm(), requested_ids, gather_functor, action_functor, ex);
696 parent_id_map.swap(child_id_map);
697 child_id_map.clear();
700 #endif // LIBMESH_ENABLE_AMR 702 libmesh_assert_equal_to (next_global_elem,
n_elem);
715 std::vector<dof_id_type> xfer_ids;
716 std::vector<Real> xfer_coords;
717 std::vector<Real> & coords=xfer_coords;
719 std::vector<std::vector<dof_id_type>> recv_ids (this->
n_processors());
720 std::vector<std::vector<Real>> recv_coords(this->
n_processors());
723 std::size_t n_written=0;
732 for (std::size_t blk=0, last_node=0; last_node<max_node_id; blk++)
734 const std::size_t first_node = blk*
io_blksize;
735 last_node = std::min((blk+1)*
io_blksize, std::size_t(max_node_id));
737 const std::size_t tot_id_size = last_node - first_node;
743 for (; node_iter != nodes_end; ++node_iter)
745 const Node & node = **node_iter;
746 libmesh_assert_greater_equal(node.
id(), first_node);
747 if (node.
id() >= last_node)
750 xfer_ids.push_back(node.
id());
751 xfer_coords.push_back(node(0));
753 xfer_coords.push_back(node(1));
756 xfer_coords.push_back(node(2));
762 std::vector<std::size_t> ids_size;
764 const std::size_t my_ids_size = xfer_ids.size();
767 this->
comm().
gather (0, my_ids_size, ids_size);
771 std::vector<Parallel::Request>
784 recv_ids[pid].resize(ids_size[pid]);
785 recv_coords[pid].resize(ids_size[pid]*LIBMESH_DIM);
789 recv_ids[0] = xfer_ids;
790 recv_coords[0] = xfer_coords;
795 id_request_handles[pid-1],
798 coord_request_handles[pid-1],
806 this->
comm().
send(0, xfer_ids, id_tag);
807 this->
comm().
send(0, xfer_coords, coord_tag);
817 Parallel::wait (id_request_handles);
818 Parallel::wait (coord_request_handles);
822 libmesh_assert_equal_to(recv_coords[pid].size(),
823 recv_ids[pid].size()*LIBMESH_DIM);
839 coords.resize (3*tot_id_size, std::numeric_limits<Real>::quiet_NaN());
844 libmesh_assert_less_equal(first_node, recv_ids[pid][
idx]);
845 const std::size_t local_idx = recv_ids[pid][
idx] - first_node;
846 libmesh_assert_less(local_idx, tot_id_size);
848 libmesh_assert_less ((3*local_idx+2), coords.size());
849 libmesh_assert_less ((LIBMESH_DIM*
idx+LIBMESH_DIM-1), recv_coords[pid].size());
851 coords[3*local_idx+0] = recv_coords[pid][LIBMESH_DIM*
idx+0];
853 coords[3*local_idx+1] = recv_coords[pid][LIBMESH_DIM*
idx+1];
855 coords[3*local_idx+1] = 0.;
858 coords[3*local_idx+2] = recv_coords[pid][LIBMESH_DIM*
idx+2];
860 coords[3*local_idx+2] = 0.;
868 io.
data_stream (coords.empty() ? nullptr : coords.data(),
869 cast_int<unsigned int>(coords.size()), 3);
874 libmesh_assert_less_equal (n_written, max_node_id);
876 #ifdef LIBMESH_ENABLE_UNIQUE_ID 878 unsigned short write_unique_ids = 1;
880 unsigned short write_unique_ids = 0;
884 io.
data (write_unique_ids,
"# presence of unique ids");
886 #ifdef LIBMESH_ENABLE_UNIQUE_ID 888 std::vector<xdr_id_type> xfer_unique_ids;
889 std::vector<xdr_id_type> & unique_ids=xfer_unique_ids;
890 std::vector<std::vector<xdr_id_type>> recv_unique_ids (this->
n_processors());
898 node_iter =
mesh.local_nodes_begin();
900 for (std::size_t blk=0, last_node=0; last_node<max_node_id; blk++)
902 const std::size_t first_node = blk*
io_blksize;
903 last_node = std::min((blk+1)*
io_blksize, std::size_t(max_node_id));
905 const std::size_t tot_id_size = last_node - first_node;
909 xfer_ids.reserve(tot_id_size);
910 xfer_unique_ids.clear();
911 xfer_unique_ids.reserve(tot_id_size);
913 for (; node_iter != nodes_end; ++node_iter)
915 const Node & node = **node_iter;
916 libmesh_assert_greater_equal(node.
id(), first_node);
917 if (node.
id() >= last_node)
920 xfer_ids.push_back(node.
id());
921 xfer_unique_ids.push_back(node.
unique_id());
926 std::vector<std::size_t> ids_size;
928 const std::size_t my_ids_size = xfer_ids.size();
931 this->
comm().
gather (0, my_ids_size, ids_size);
935 std::vector<Parallel::Request>
948 recv_ids[pid].resize(ids_size[pid]);
949 recv_unique_ids[pid].resize(ids_size[pid]);
953 recv_ids[0] = xfer_ids;
954 recv_unique_ids[0] = xfer_unique_ids;
959 id_request_handles[pid-1],
962 unique_id_request_handles[pid-1],
970 this->
comm().
send(0, xfer_ids, id_tag);
971 this->
comm().
send(0, xfer_unique_ids, unique_id_tag);
981 Parallel::wait (id_request_handles);
982 Parallel::wait (unique_id_request_handles);
986 libmesh_assert_equal_to
987 (recv_ids[pid].size(), recv_unique_ids[pid].size());
990 libmesh_assert_less_equal
991 (tot_id_size, std::min(
io_blksize, std::size_t(max_node_id)));
1000 libmesh_assert_less_equal(first_node, recv_ids[pid][
idx]);
1001 const std::size_t local_idx = recv_ids[pid][
idx] - first_node;
1002 libmesh_assert_less (local_idx, unique_ids.size());
1004 unique_ids[local_idx] = recv_unique_ids[pid][
idx];
1011 io.
data_stream (unique_ids.empty() ? nullptr : unique_ids.data(),
1012 cast_int<unsigned int>(unique_ids.size()), 1);
1017 libmesh_assert_less_equal (n_written, max_node_id);
1019 #endif // LIBMESH_ENABLE_UNIQUE_ID 1022 if (n_node_integers)
1030 node_iter =
mesh.local_nodes_begin();
1033 std::vector<dof_id_type> xfer_node_integers;
1034 std::vector<dof_id_type> & node_integers = xfer_node_integers;
1035 std::vector<std::vector<dof_id_type>> recv_node_integers(this->
n_processors());
1037 for (std::size_t blk=0, last_node=0; last_node<max_node_id; blk++)
1039 const std::size_t first_node = blk*
io_blksize;
1040 last_node = std::min((blk+1)*
io_blksize, std::size_t(max_node_id));
1042 const std::size_t tot_id_size = last_node - first_node;
1046 xfer_ids.reserve(tot_id_size);
1047 xfer_node_integers.clear();
1048 xfer_node_integers.reserve(tot_id_size * n_node_integers);
1050 for (; node_iter != nodes_end; ++node_iter)
1052 const Node & node = **node_iter;
1053 libmesh_assert_greater_equal(node.
id(), first_node);
1054 if (node.
id() >= last_node)
1057 xfer_ids.push_back(node.
id());
1060 for (
unsigned int i=0; i != n_node_integers; ++i)
1066 std::vector<std::size_t> ids_size;
1068 const std::size_t my_ids_size = xfer_ids.size();
1071 this->
comm().
gather (0, my_ids_size, ids_size);
1075 std::vector<Parallel::Request>
1088 recv_ids[pid].resize(ids_size[pid]);
1089 recv_node_integers[pid].resize(n_node_integers * ids_size[pid]);
1093 recv_ids[0] = xfer_ids;
1094 recv_node_integers[0] = xfer_node_integers;
1099 id_request_handles[pid-1],
1101 this->
comm().
receive (pid, recv_node_integers[pid],
1102 node_integers_request_handles[pid-1],
1110 this->
comm().
send(0, xfer_ids, id_tag);
1111 this->
comm().
send(0, xfer_node_integers, node_integers_tag);
1121 Parallel::wait (id_request_handles);
1122 Parallel::wait (node_integers_request_handles);
1126 libmesh_assert_equal_to
1127 (recv_ids[pid].size(), recv_node_integers[pid].size() / n_node_integers);
1130 libmesh_assert_less_equal
1131 (tot_id_size, std::min(
io_blksize, std::size_t(max_node_id)));
1146 node_integers.clear();
1147 node_integers.resize (n_node_integers*tot_id_size, static_cast<dof_id_type>(-1));
1152 libmesh_assert_less_equal(first_node, recv_ids[pid][
idx]);
1153 const std::size_t local_idx = recv_ids[pid][
idx] - first_node;
1156 libmesh_assert_less (local_idx, tot_id_size);
1158 for (
unsigned int i=0; i != n_node_integers; ++i)
1159 node_integers[n_node_integers*local_idx + i] = recv_node_integers[pid][n_node_integers*
idx + i];
1166 io.
data_stream (node_integers.empty() ? nullptr : node_integers.data(),
1167 cast_int<unsigned int>(node_integers.size()), n_node_integers);
1172 libmesh_assert_less_equal (n_written, max_node_id);
1195 std::stringstream comment_string;
1196 comment_string <<
"# number of " << bc_type <<
" boundary conditions";
1197 io.
data (n_bcs_out, comment_string.str());
1203 std::vector<xdr_id_type> xfer_bcs, recv_bcs;
1204 std::vector<std::size_t> bc_sizes(this->
n_processors());
1207 std::vector<boundary_id_type> bc_ids;
1211 for (
const auto & elem :
as_range(
mesh.local_level_elements_begin(0),
1212 mesh.local_level_elements_end(0)))
1214 if (bc_type ==
"side")
1216 for (
auto s : elem->side_index_range())
1219 for (
const auto & bc_id : bc_ids)
1222 xfer_bcs.push_back (n_local_level_0_elem);
1223 xfer_bcs.push_back (s) ;
1224 xfer_bcs.push_back (bc_id);
1228 else if (bc_type ==
"edge")
1230 for (
auto e : elem->edge_index_range())
1233 for (
const auto & bc_id : bc_ids)
1236 xfer_bcs.push_back (n_local_level_0_elem);
1237 xfer_bcs.push_back (e) ;
1238 xfer_bcs.push_back (bc_id);
1242 else if (bc_type ==
"shellface")
1244 for (
unsigned short sf=0; sf<2; sf++)
1247 for (
const auto & bc_id : bc_ids)
1250 xfer_bcs.push_back (n_local_level_0_elem);
1251 xfer_bcs.push_back (sf) ;
1252 xfer_bcs.push_back (bc_id);
1258 libmesh_error_msg(
"bc_type not recognized: " + bc_type);
1262 n_local_level_0_elem++;
1265 xfer_bcs.push_back(n_local_level_0_elem);
1266 std::size_t my_size = xfer_bcs.size();
1276 recv_bcs.resize(bc_sizes[pid]);
1278 recv_bcs = xfer_bcs;
1283 = cast_int<dof_id_type>(recv_bcs.back());
1284 recv_bcs.pop_back();
1286 for (std::size_t
idx=0, rbs=recv_bcs.size();
idx<rbs;
idx += 3, n_bcs_out++)
1287 recv_bcs[
idx+0] += elem_offset;
1289 io.
data_stream (recv_bcs.empty() ? nullptr : recv_bcs.data(),
1290 cast_int<unsigned int>(recv_bcs.size()), 3);
1291 elem_offset += my_n_local_level_0_elem;
1293 libmesh_assert_equal_to (n_bcs, n_bcs_out);
1337 io.
data (n_nodesets_out,
"# number of nodesets");
1340 if (!n_nodesets)
return;
1342 std::vector<xdr_id_type> xfer_bcs, recv_bcs;
1343 std::vector<std::size_t> bc_sizes(this->
n_processors());
1346 std::vector<boundary_id_type> nodeset_ids;
1349 for (
const auto & node :
mesh.local_node_ptr_range())
1352 for (
const auto & bc_id : nodeset_ids)
1355 xfer_bcs.push_back (node->id());
1356 xfer_bcs.push_back (bc_id);
1360 xfer_bcs.push_back(n_node);
1361 std::size_t my_size = xfer_bcs.size();
1371 recv_bcs.resize(bc_sizes[pid]);
1373 recv_bcs = xfer_bcs;
1378 cast_int<dof_id_type>(recv_bcs.back());
1379 recv_bcs.pop_back();
1381 for (std::size_t
idx=0, rbs=recv_bcs.size();
idx<rbs;
idx += 2, n_nodesets_out++)
1382 recv_bcs[
idx+0] += node_offset;
1384 io.
data_stream (recv_bcs.empty() ? nullptr : recv_bcs.data(),
1385 cast_int<unsigned int>(recv_bcs.size()), 2);
1386 node_offset += my_n_node;
1388 libmesh_assert_equal_to (n_nodesets, n_nodesets_out);
1400 const std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
1401 info.get_sideset_name_map() :
info.get_nodeset_name_map();
1403 std::vector<new_header_id_type> boundary_ids;
1404 boundary_ids.reserve(boundary_map.size());
1406 std::vector<std::string> boundary_names;
1407 boundary_names.reserve(boundary_map.size());
1413 for (
const auto & [bndry_id,
name] : boundary_map)
1417 boundary_ids.push_back(bndry_id);
1418 boundary_names.push_back(
name);
1422 io.
data(n_boundary_names,
"# sideset id to name map");
1424 io.
data(n_boundary_names,
"# nodeset id to name map");
1426 if (n_boundary_names)
1428 io.
data(boundary_ids);
1429 io.
data(boundary_names);
1438 LOG_SCOPE(
"read()",
"XdrIO");
1458 libmesh_error_msg_if(this->
legacy(),
"We no longer support reading files in the legacy format.");
1462 const unsigned int n_header_metadata_values = 13;
1463 std::vector<new_header_id_type> meta_data(n_header_metadata_values,
sizeof(
xdr_id_type));
1472 std::vector<old_header_id_type> old_data(n_header_metadata_values,
sizeof(
xdr_id_type));
1476 meta_data.assign(old_data.begin(), old_data.end());
1504 uint32_t type_size = 0;
1533 uint64_t type_size = 0;
1567 template <
typename T>
1570 LOG_SCOPE(
"read_header()",
"XdrIO");
1577 std::vector<std::string> node_integer_names;
1578 std::vector<std::string> elem_integer_names;
1579 std::vector<dof_id_type> elemset_codes;
1580 std::vector<std::vector<dof_id_type>> elemset_id_vecs;
1584 io.
data (meta_data[0]);
1585 io.
data (meta_data[1]);
1594 libmesh_assert_greater_equal(meta_data.size(), 10);
1596 io.
data (meta_data[2],
"# type size");
1597 io.
data (meta_data[3],
"# uid size");
1598 io.
data (meta_data[4],
"# pid size");
1599 io.
data (meta_data[5],
"# sid size");
1600 io.
data (meta_data[6],
"# p-level size");
1602 io.
data (meta_data[7],
"# eid size");
1603 io.
data (meta_data[8],
"# side size");
1604 io.
data (meta_data[9],
"# bid size");
1610 libmesh_assert_greater_equal(meta_data.size(), 13);
1612 io.
data (meta_data[10],
"# extra integer size");
1615 io.
data(node_integer_names,
"# node integer names");
1616 meta_data[11] = node_integer_names.size();
1619 io.
data(elem_integer_names,
"# elem integer names");
1620 meta_data[12] = elem_integer_names.size();
1623 io.
data(elemset_codes,
"# elemset codes");
1626 elemset_id_vecs.resize(elemset_codes.size());
1628 io.
data(elemset_id_vecs[i]);
1646 const T &
n_elem = meta_data[0];
1647 const T &
n_nodes = meta_data[1];
1675 elemset_id_vecs[i].end()));
1684 if (read_entity_info)
1689 std::vector<new_header_id_type> subdomain_ids;
1690 std::vector<std::string> subdomain_names;
1695 if (use_new_header_type)
1696 io.
data(n_subdomain_names);
1701 n_subdomain_names = temp;
1704 subdomain_ids.resize(n_subdomain_names);
1705 subdomain_names.resize(n_subdomain_names);
1707 if (n_subdomain_names)
1709 if (use_new_header_type)
1710 io.
data(subdomain_ids);
1713 std::vector<old_header_id_type> temp;
1715 subdomain_ids.assign(temp.begin(), temp.end());
1718 io.
data(subdomain_names);
1724 if (n_subdomain_names == 0)
1727 subdomain_ids.resize(n_subdomain_names);
1728 subdomain_names.resize(n_subdomain_names);
1735 for (
unsigned int i=0; i<n_subdomain_names; ++i)
1736 subdomain_map.emplace(subdomain_ids[i], subdomain_names[i]);
1741 template <
typename T>
1745 const std::vector<new_header_id_type> & meta_data,
1764 std::vector<T> conn, input_buffer(100 );
1769 const size_t unique_id_size_index = 3;
1771 const bool read_unique_id =
1773 meta_data[unique_id_size_index];
1776 const std::size_t n_elem_integers_index = 12;
1780 libmesh_assert_greater_equal(meta_data.size(), 13);
1781 n_elem_integers = meta_data[n_elem_integers_index];
1784 T n_elem_at_level=0, n_processed_at_level=0;
1785 for (
dof_id_type blk=0, first_elem=0, last_elem=0;
1788 first_elem = cast_int<dof_id_type>(blk*
io_blksize);
1789 last_elem = cast_int<dof_id_type>(std::min(cast_int<std::size_t>((blk+1)*
io_blksize),
1790 cast_int<std::size_t>(
n_elem)));
1795 for (
dof_id_type e=first_elem; e<last_elem; e++, n_processed_at_level++)
1797 if (n_processed_at_level == n_elem_at_level)
1800 io.
data (n_elem_at_level);
1801 n_processed_at_level = 0;
1806 unsigned int pos = 0;
1821 input_buffer[pos++] =
static_cast<T
>(-1);
1824 if (read_partitioning)
1827 input_buffer[pos++] = 0;
1830 if (read_subdomain_id)
1833 input_buffer[pos++] = 0;
1839 input_buffer[pos++] = 0;
1843 libmesh_not_implemented();
1846 libmesh_assert_less (pos+n_nodes0, input_buffer.size());
1853 libmesh_assert_less (pos + n_elem_integers, input_buffer.size());
1854 io.
data_stream (&input_buffer[pos], n_elem_integers);
1857 pos += n_elem_integers;
1860 conn.insert (conn.end(), input_buffer.begin(), input_buffer.begin() + pos);
1863 std::size_t conn_size = conn.size();
1865 conn.resize (conn_size);
1869 for (
auto [e, it] = std::tuple{first_elem, conn.begin()}; e<last_elem; e++)
1876 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1887 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1888 unique_id = cast_int<unique_id_type>(tmp);
1897 cast_int<processor_id_type>(*it++);
1900 cast_int<subdomain_id_type>(*it++);
1903 #ifdef LIBMESH_ENABLE_AMR 1904 const unsigned int p_level = cast_int<unsigned int>(tmp);
1913 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1914 elem->set_unique_id(unique_id);
1916 elem->processor_id() = proc_id;
1917 elem->subdomain_id() = subdomain_id;
1918 #ifdef LIBMESH_ENABLE_AMR 1919 elem->hack_p_level(p_level);
1923 parent->add_child(elem.get());
1930 for (
unsigned int n=0, n_n = elem->n_nodes(); n != n_n;
1934 cast_int<dof_id_type>(*it);
1939 elem->set_node(n, node);
1943 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1945 new_node->set_unique_id(
n_elem + global_node_number);
1962 for (
unsigned int ei=0; ei<n_elem_integers; ++ei)
1964 auto extra_int = cast_int<dof_id_type>(*it++);
1971 for (
unsigned char i=0; i!=4; ++i)
1977 "Cannot open dimension " 1979 <<
" mesh file when configured without " 1990 const std::vector<new_header_id_type> & meta_data)
2011 std::vector<dof_id_type> needed_nodes;
2014 for (
auto & node :
mesh.node_ptr_range())
2015 needed_nodes.push_back(node->id());
2017 std::sort (needed_nodes.begin(), needed_nodes.end());
2020 libmesh_assert (std::unique(needed_nodes.begin(), needed_nodes.end()) == needed_nodes.end());
2024 const std::size_t n_node_integers_index = 11;
2028 libmesh_assert_greater_equal(meta_data.size(), 13);
2029 n_node_integers = meta_data[n_node_integers_index];
2033 std::vector<Real> coords;
2034 std::pair<std::vector<dof_id_type>::iterator,
2035 std::vector<dof_id_type>::iterator> pos;
2036 pos.first = needed_nodes.begin();
2039 for (std::size_t blk=0, first_node=0, last_node=0; last_node<
n_nodes; blk++)
2044 coords.resize(3*(last_node - first_node));
2047 io.
data_stream (coords.empty() ? nullptr : coords.data(),
2048 cast_int<unsigned int>(coords.size()));
2055 for (std::size_t n=first_node,
idx=0; n<last_node; n++,
idx+=3)
2060 pos = std::equal_range (pos.first, needed_nodes.end(), n);
2062 if (pos.first != pos.second)
2064 libmesh_assert_equal_to (*pos.first, n);
2078 unsigned short read_unique_ids =
false;
2083 io.
data (read_unique_ids);
2092 if (!read_unique_ids)
2094 #ifdef LIBMESH_ENABLE_UNIQUE_ID 2096 for (
auto & elem :
mesh.element_ptr_range())
2097 max_elem_unique_id = std::max(max_elem_unique_id,
2098 elem->unique_id()+1);
2101 for (
auto & node :
mesh.node_ptr_range())
2102 node->set_unique_id(max_elem_unique_id + node->id());
2109 std::vector<uint32_t> unique_32;
2110 std::vector<uint64_t> unique_64;
2113 pos.first = needed_nodes.begin();
2115 for (std::size_t blk=0, first_node=0, last_node=0; last_node<
n_nodes; blk++)
2123 unique_64.resize(last_node - first_node);
2125 unique_32.resize(last_node - first_node);
2130 io.
data_stream (unique_64.empty() ? nullptr : unique_64.data(),
2131 cast_int<unsigned int>(unique_64.size()));
2133 io.
data_stream (unique_32.empty() ? nullptr : unique_32.data(),
2134 cast_int<unsigned int>(unique_32.size()));
2137 #ifdef LIBMESH_ENABLE_UNIQUE_ID 2143 for (std::size_t n=first_node,
idx=0; n<last_node; n++,
idx++)
2148 pos = std::equal_range (pos.first, needed_nodes.end(), n);
2150 if (pos.first != pos.second)
2152 libmesh_assert_equal_to (*pos.first, n);
2159 #endif // LIBMESH_ENABLE_UNIQUE_ID 2167 if (n_node_integers)
2169 std::vector<dof_id_type> extra_integers;
2172 pos.first = needed_nodes.begin();
2174 for (std::size_t blk=0, first_node=0, last_node=0; last_node<
n_nodes; blk++)
2179 extra_integers.resize((last_node - first_node) * n_node_integers);
2183 io.
data_stream (extra_integers.empty() ? nullptr : extra_integers.data(),
2184 cast_int<unsigned int>(extra_integers.size()));
2189 for (std::size_t n=first_node,
idx=0; n<last_node; n++,
idx++)
2194 pos = std::equal_range (pos.first, needed_nodes.end(), n);
2196 if (pos.first != pos.second)
2198 libmesh_assert_equal_to (*pos.first, n);
2201 for (
unsigned int i=0; i != n_node_integers; ++i)
2211 template <
typename T>
2227 std::vector<T> input_buffer;
2243 for (std::size_t blk=0, first_bc=0, last_bc=0; last_bc<n_bcs; blk++)
2246 last_bc = std::min((blk+1)*
io_blksize, std::size_t(n_bcs));
2248 input_buffer.resize (3*(last_bc - first_bc));
2251 io.
data_stream (input_buffer.empty() ? nullptr : input_buffer.data(),
2252 cast_int<unsigned int>(input_buffer.size()));
2261 for (std::size_t
idx=0, ibs=input_buffer.size();
idx<ibs;
idx+=3)
2264 cast_int<dof_id_type>(input_buffer[
idx+0]);
2265 const unsigned short side =
2266 cast_int<unsigned short>(input_buffer[
idx+1]);
2268 cast_int<boundary_id_type>(input_buffer[
idx+2]);
2274 if (bc_type ==
"side")
2276 libmesh_assert_less (side, elem->n_sides());
2277 boundary_info.
add_side (elem, side, bc_id);
2279 else if (bc_type ==
"edge")
2281 libmesh_assert_less (side, elem->n_edges());
2282 boundary_info.
add_edge (elem, side, bc_id);
2284 else if (bc_type ==
"shellface")
2287 libmesh_assert_less(side, 2);
2293 libmesh_error_msg(
"bc_type not recognized: " + bc_type);
2296 input_buffer.clear();
2302 template <
typename T>
2310 template <
typename T>
2318 template <
typename T>
2326 template <
typename T>
2342 std::vector<T> input_buffer;
2348 io.
data (n_nodesets);
2358 for (std::size_t blk=0, first_bc=0, last_bc=0; last_bc<n_nodesets; blk++)
2361 last_bc = std::min((blk+1)*
io_blksize, std::size_t(n_nodesets));
2363 input_buffer.resize (2*(last_bc - first_bc));
2366 io.
data_stream (input_buffer.empty() ? nullptr : input_buffer.data(),
2367 cast_int<unsigned int>(input_buffer.size()));
2374 for (std::size_t
idx=0, ibs=input_buffer.size();
idx<ibs;
idx+=2)
2377 cast_int<dof_id_type>(input_buffer[
idx+0]);
2379 cast_int<boundary_id_type>(input_buffer[
idx+1]);
2383 boundary_info.
add_node (node, bc_id);
2385 input_buffer.clear();
2395 if (read_entity_info)
2398 std::vector<new_header_id_type> boundary_ids;
2399 std::vector<std::string> boundary_names;
2404 if (use_new_header_type)
2405 io.
data(n_boundary_names);
2410 n_boundary_names = temp;
2413 boundary_names.resize(n_boundary_names);
2415 if (n_boundary_names)
2417 if (use_new_header_type)
2418 io.
data(boundary_ids);
2421 std::vector<old_header_id_type> temp(n_boundary_names);
2423 boundary_ids.assign(temp.begin(), temp.end());
2425 io.
data(boundary_names);
2431 if (n_boundary_names == 0)
2434 boundary_ids.resize(n_boundary_names);
2435 boundary_names.resize(n_boundary_names);
2440 std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
2441 info.set_sideset_name_map() :
info.set_nodeset_name_map();
2443 for (
unsigned int i=0; i<n_boundary_names; ++i)
2444 boundary_map.emplace(cast_int<boundary_id_type>(boundary_ids[i]), boundary_names[i]);
2459 conn.push_back(elem->
n_nodes());
2461 conn.push_back (elem->
type());
2470 conn.push_back (parent_id);
2472 conn.push_back (parent_pid);
2478 #ifdef LIBMESH_ENABLE_AMR 2479 conn.push_back (elem->
p_level());
2483 conn.push_back (elem->
node_id(n));
2486 for (
unsigned int i=0; i != n_elem_integers; ++i)
2493 (this->
version().find(
"0.9.2") != std::string::npos) ||
2494 (this->
version().find(
"0.9.6") != std::string::npos) ||
2495 (this->
version().find(
"1.1.0") != std::string::npos) ||
2496 (this->
version().find(
"1.3.0") != std::string::npos) ||
2497 (this->
version().find(
"1.8.0") != std::string::npos);
2503 (this->
version().find(
"0.9.6") != std::string::npos) ||
2504 (this->
version().find(
"1.1.0") != std::string::npos) ||
2505 (this->
version().find(
"1.3.0") != std::string::npos) ||
2506 (this->
version().find(
"1.8.0") != std::string::npos);
2512 (this->
version().find(
"1.1.0") != std::string::npos) ||
2513 (this->
version().find(
"1.3.0") != std::string::npos) ||
2514 (this->
version().find(
"1.8.0") != std::string::npos);
2520 (this->
version().find(
"1.3.0") != std::string::npos) ||
2521 (this->
version().find(
"1.8.0") != std::string::npos);
2527 (this->
version().find(
"1.8.0") != std::string::npos);
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
void write_serialized_nodesets(Xdr &io, const new_header_id_type n_nodesets) const
Write the boundary conditions for a parallel, distributed mesh.
std::size_t n_boundary_conds() const
std::vector< unsigned int > add_elem_integers(const std::vector< std::string > &names, bool allocate_data=true, const std::vector< dof_id_type > *default_values=nullptr)
Register integer data (of type dof_id_type) to be added to each element in the mesh, one string name for each new integer.
ElemType
Defines an enum for geometric element types.
XdrIO(MeshBase &, const bool=false)
Constructor.
unique_id_type & set_unique_id()
virtual void reserve_nodes(const dof_id_type nn)=0
Reserves space for a known number of nodes.
void read_serialized_nodes(Xdr &io, const dof_id_type n_nodes, const std::vector< new_header_id_type > &meta_data)
Read the nodal locations for a parallel, distributed mesh.
A Node is like a Point, but with more information.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
unsigned int n_node_integers() const
bool write_parallel() const
Report whether we should write parallel files.
std::vector< dof_id_type > get_elemset_codes() const
Return a vector of all elemset codes defined on the mesh.
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
bool version_at_least_0_9_6() const
std::size_t n_edge_conds() const
void write_serialized_side_bcs(Xdr &io, const new_header_id_type n_side_bcs) const
Write the side boundary conditions for a parallel, distributed mesh.
void read_serialized_subdomain_names(Xdr &io)
Read subdomain name information - NEW in 0.9.2 format.
void read_serialized_bcs_helper(Xdr &io, T type_size, const std::string bc_type)
Helper function used in read_serialized_side_bcs, read_serialized_edge_bcs, and read_serialized_shell...
bool legacy() const
Get/Set the flag indicating if we should read/write legacy.
void gather(const unsigned int root_id, const T &send_data, std::vector< T, A > &recv) const
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.
std::size_t n_shellface_conds() const
void close()
Closes the file if it is open.
void add_elemset_code(dof_id_type code, MeshBase::elemset_type id_set)
Tabulate a user-defined "code" for elements which belong to the element sets specified in id_set...
unsigned int n_elem_integers() const
This is the base class from which all geometric element types are derived.
uint32_t old_header_id_type
void read_serialized_nodesets(Xdr &io, T type_size)
Read the nodeset conditions for a parallel, distributed mesh.
unique_id_type unique_id() const
const Parallel::Communicator & comm() const
std::vector< unsigned int > add_node_integers(const std::vector< std::string > &names, bool allocate_data=true, const std::vector< dof_id_type > *default_values=nullptr)
Register integer data (of type dof_id_type) to be added to each node in the mesh. ...
unsigned int p_level() const
void write_serialized_subdomain_names(Xdr &io) const
Write subdomain name information - NEW in 0.9.2 format.
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
This class defines an abstract interface for Mesh output.
virtual void set_next_unique_id(unique_id_type id)=0
Sets the next available unique id to be used.
void read_serialized_side_bcs(Xdr &io, T type_size)
Read the side boundary conditions for a parallel, distributed mesh.
void read_serialized_shellface_bcs(Xdr &io, T type_size)
Read the "shell face" boundary conditions for a parallel, distributed mesh.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
void write_serialized_nodes(Xdr &io, const dof_id_type n_nodes, const new_header_id_type n_node_integers) const
Write the nodal locations for a parallel, distributed mesh.
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...
const std::string & get_elem_integer_name(unsigned int i) const
void read_serialized_bc_names(Xdr &io, BoundaryInfo &info, bool is_sideset)
Read boundary names information (sideset and nodeset) - NEW in 0.9.2 format.
uint8_t processor_id_type
This is the MeshBase class.
void get_elemsets(dof_id_type elemset_code, MeshBase::elemset_type &id_set_to_fill) const
Look up the element sets for a given elemset code and vice-versa.
void data(T &a, std::string_view comment="")
Inputs or outputs a single value.
largest_id_type xdr_id_type
void read_serialized_edge_bcs(Xdr &io, T type_size)
Read the edge boundary conditions for a parallel, distributed mesh.
processor_id_type n_processors() const
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
const dof_id_type n_nodes
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
static const boundary_id_type invalid_id
Number used for internal use.
const std::string & boundary_condition_file_name() const
Get/Set the boundary condition file name.
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
virtual unsigned int n_nodes() const =0
bool version_at_least_1_3_0() const
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
virtual void write(const std::string &) override
This method implements writing a mesh to a specified file.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
const std::string & subdomain_map_file_name() const
Get/Set the subdomain file name.
virtual const Node * query_node_ptr(const dof_id_type i) const =0
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
unsigned int _field_width
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
void read_header(Xdr &io, std::vector< T > &meta_data)
Read header information - templated to handle old (4-byte) or new (8-byte) header id types...
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
void write_serialized_bc_names(Xdr &io, const BoundaryInfo &info, bool is_sideset) const
Write boundary names information (sideset and nodeset) - NEW in 0.9.2 format.
bool version_at_least_1_1_0() const
An object whose state is distributed along a set of processors.
uint64_t new_header_id_type
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
This class implements a C++ interface to the XDR (eXternal Data Representation) format.
const std::string & partition_map_file_name() const
Get/Set the partitioning file name.
virtual Node * add_node(Node *n)=0
Add Node n to the end of the vertex array.
virtual const Elem * elem_ptr(const dof_id_type i) const =0
void write_serialized_connectivity(Xdr &io, const dof_id_type n_elem, const new_header_id_type n_elem_integers) const
Write the connectivity for a parallel, distributed mesh.
static std::unique_ptr< Node > build(const Node &n)
std::set< elemset_id_type > elemset_type
Typedef for the "set" container used to store elemset ids.
subdomain_id_type n_subdomains() const
const std::string & version() const
Get/Set the version string.
const std::string & polynomial_level_file_name() const
Get/Set the polynomial degree file name.
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
subdomain_id_type subdomain_id() const
static const std::size_t io_blksize
Define the block size to use for chunked IO.
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
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...
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
Add shell face shellface of element number elem with boundary id id to the boundary information data ...
The definition of the const_node_iterator struct.
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...
unsigned int mesh_dimension() const
virtual ~XdrIO()
Destructor.
std::size_t n_nodeset_conds() const
IntRange< unsigned short > node_index_range() const
bool version_at_least_0_9_2() const
void pack_element(std::vector< xdr_id_type > &conn, const Elem *elem, const dof_id_type parent_id, const dof_id_type parent_pid, const new_header_id_type n_elem_integers) const
Pack an element into a transfer buffer for parallel communication.
const std::string & get_node_integer_name(unsigned int i) const
unsigned int n_extra_integers() const
Returns how many extra integers are associated to the DofObject.
void read_serialized_connectivity(Xdr &io, const dof_id_type n_elem, const std::vector< new_header_id_type > &meta_data, T type_size)
Read the connectivity for a parallel, distributed mesh.
virtual const Node & node_ref(const dof_id_type i) const
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
void write_serialized_shellface_bcs(Xdr &io, const new_header_id_type n_shellface_bcs) const
Write the "shell face" boundary conditions for a parallel, distributed mesh.
bool binary() const
Get/Set the flag indicating if we should read/write binary.
void write_serialized_bcs_helper(Xdr &io, const new_header_id_type n_side_bcs, const std::string bc_type) const
Helper function used in write_serialized_side_bcs, write_serialized_edge_bcs, and write_serialized_sh...
virtual dof_id_type max_node_id() const =0
virtual dof_id_type n_elem() const =0
processor_id_type processor_id() const
void data_stream(T *val, const unsigned int len, const unsigned int line_break=libMesh::invalid_uint)
Inputs or outputs a raw data stream.
const DofMap &dof_map LIBMESH_COMMA unsigned int std::string & set_subdomain_name_map()
processor_id_type processor_id() const
virtual ElemType type() const =0
void write_serialized_edge_bcs(Xdr &io, const new_header_id_type n_edge_bcs) const
Write the edge boundary conditions for a parallel, distributed mesh.
A Point defines a location in LIBMESH_DIM dimensional Real space.
dof_id_type node_id(const unsigned int i) const
virtual void reserve_elem(const dof_id_type ne)=0
Reserves space for a known number of elements.
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 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...
virtual dof_id_type n_nodes() const =0
virtual void read(const std::string &) override
This method implements reading a mesh from a specified file.
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...
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...
bool version_at_least_1_8_0() const