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/xdr_cxx.h" 52 template <
class T,
class U>
53 struct libmesh_type_is_same {
54 static const bool value =
false;
58 struct libmesh_type_is_same<T, T> {
59 static const bool value =
true;
80 _write_serial (false),
81 _write_parallel (false),
82 #ifdef LIBMESH_ENABLE_UNIQUE_ID
83 _write_unique_id (true),
85 _write_unique_id (false),
88 _version (
"libMesh-1.8.0"),
89 _bc_file_name (
"n/a"),
90 _partition_map_file (
"n/a"),
91 _subdomain_map_file (
"n/a"),
104 _write_serial (false),
105 _write_parallel (false),
106 #ifdef LIBMESH_ENABLE_UNIQUE_ID
107 _write_unique_id (true),
109 _write_unique_id (false),
112 _version (
"libMesh-1.8.0"),
113 _bc_file_name (
"n/a"),
114 _partition_map_file (
"n/a"),
115 _subdomain_map_file (
"n/a"),
116 _p_level_file (
"n/a")
128 libmesh_error_msg_if(this->
legacy(),
"We don't support writing parallel files in the legacy format.");
132 LOG_SCOPE(
"write()",
"XdrIO");
157 if ((n_side_bcs || n_edge_bcs || n_shellface_bcs || n_nodesets) &&
171 if ((n_p_levels > 1) &&
178 std::string full_ver = this->
version() + (write_parallel_files ?
" parallel" :
"");
182 io.
data (max_node_id,
"# number of nodes");
198 io.
data (write_size,
"# type size");
200 io.
data (write_partitioning ? write_size : zero_size,
"# pid size");
201 io.
data (write_subdomain_id ? write_size : zero_size,
"# sid size");
202 io.
data (write_p_level ? write_size : zero_size,
"# p-level size");
204 io.
data (write_bcs ? write_size : zero_size,
"# eid size");
205 io.
data (write_bcs ? write_size : zero_size,
"# side size");
206 io.
data (write_bcs ? write_size : zero_size,
"# bid size");
210 io.
data((n_elem_integers || n_node_integers) ? write_size : zero_size,
"# extra integer size");
213 std::vector<std::string> node_integer_names;
214 for (
unsigned int i=0; i != n_node_integers; ++i)
216 io.
data(node_integer_names,
"# node integer names");
219 std::vector<std::string> elem_integer_names;
220 for (
unsigned int i=0; i != n_elem_integers; ++i)
222 io.
data(elem_integer_names,
"# elem integer names");
227 io.
data(elemset_codes,
"# elemset codes");
231 for (
const auto & elemset_code : elemset_codes)
236 std::vector<dof_id_type> elemset_id_vec(id_set_to_fill.begin(), id_set_to_fill.end());
239 std::string comment_string =
"# elemset ids for elemset code " + std::to_string(elemset_code);
240 io.
data(elemset_id_vec, comment_string);
244 if (write_parallel_files)
248 libMesh::out <<
"Warning! Parallel xda/xdr is not yet implemented.\n";
249 libMesh::out <<
"Writing a serialized file instead." << std::endl;
314 std::vector<new_header_id_type> subdomain_ids;
315 subdomain_ids.reserve(subdomain_map.size());
317 std::vector<std::string> subdomain_names;
318 subdomain_names.reserve(subdomain_map.size());
324 for (
const auto & [sbd_id,
name] : subdomain_map)
328 subdomain_ids.push_back(sbd_id);
329 subdomain_names.push_back(
name);
332 io.
data(n_subdomain_names,
"# subdomain id to name map");
334 if (n_subdomain_names)
336 io.
data(subdomain_ids);
337 io.
data(subdomain_names);
370 n_global_elem_at_level[level] =
372 mesh.local_level_elements_end(level));
374 this->
comm().
sum(n_global_elem_at_level[level]);
376 tot_n_elem += n_global_elem_at_level[level];
378 libmesh_assert_less_equal (n_global_elem_at_level[level],
n_elem);
379 libmesh_assert_less_equal (tot_n_elem,
n_elem);
382 std::vector<xdr_id_type>
383 xfer_conn, recv_conn;
384 std::vector<dof_id_type>
386 std::vector<xdr_id_type> output_buffer;
387 std::vector<std::size_t>
390 #ifdef LIBMESH_ENABLE_AMR 391 typedef std::map<dof_id_type, std::pair<processor_id_type, dof_id_type>> id_map_type;
392 id_map_type parent_id_map, child_id_map;
399 for (
const auto & elem :
as_range(
mesh.local_level_elements_begin(0),
400 mesh.local_level_elements_end(0)))
406 #ifdef LIBMESH_ENABLE_AMR 407 parent_id_map[elem->id()] = std::make_pair(this->
processor_id(),
412 xfer_conn.push_back(my_next_elem);
414 std::size_t my_size = xfer_conn.size();
415 this->
comm().
gather (0, my_next_elem, n_elem_on_proc);
416 this->
comm().
gather (0, my_size, xfer_buf_sizes);
418 processor_offsets[0] = 0;
420 processor_offsets[pid] = processor_offsets[pid-1] + n_elem_on_proc[pid-1];
428 std::string comment =
"# n_elem at level 0", legend =
", [ type ";
431 if (write_partitioning)
433 if (write_subdomain_id)
436 legend +=
"p_level ";
437 legend +=
"(n0 ... nN-1) ]";
439 io.
data (n_global_elem_at_level[0], comment);
444 recv_conn.resize(xfer_buf_sizes[pid]);
446 recv_conn = xfer_conn;
454 for (
auto [elem, recv_conn_iter, n_elem_received] =
455 std::tuple{
xdr_id_type(0), recv_conn.begin(), recv_conn.back()};
456 elem<n_elem_received; elem++, next_global_elem++)
458 output_buffer.clear();
464 output_buffer.push_back(*recv_conn_iter++);
469 output_buffer.push_back(tmp);
472 tmp = *recv_conn_iter++;
473 if (write_partitioning)
474 output_buffer.push_back(tmp);
477 tmp = *recv_conn_iter++;
478 if (write_subdomain_id)
479 output_buffer.push_back(tmp);
481 #ifdef LIBMESH_ENABLE_AMR 483 tmp = *recv_conn_iter++;
485 output_buffer.push_back(tmp);
489 output_buffer.push_back(*recv_conn_iter++);
493 output_buffer.push_back(*recv_conn_iter++);
496 (output_buffer.data(),
497 cast_int<unsigned int>(output_buffer.size()),
498 cast_int<unsigned int>(output_buffer.size()));
505 #ifdef LIBMESH_ENABLE_AMR 515 for (
const auto & parent :
as_range(
mesh.local_level_elements_begin(level-1),
516 mesh.local_level_elements_end(level-1)))
517 if (!parent->active())
519 id_map_type::iterator pos = parent_id_map.find(parent->id());
523 parent_id_map.erase(pos);
525 for (
auto & child : parent->child_ref_range())
527 pack_element (xfer_conn, &child, parent_id, parent_pid, n_elem_integers);
532 child_id_map[child.id()] = std::make_pair (child.processor_id(),
533 my_n_elem_written_at_level++);
537 xfer_conn.push_back(my_n_elem_written_at_level);
538 my_size = xfer_conn.size();
539 this->
comm().
gather (0, my_size, xfer_buf_sizes);
546 std::ostringstream buf;
547 buf <<
"# n_elem at level " << level <<
", [ type ";
552 if (write_partitioning)
554 if (write_subdomain_id)
558 buf <<
"(n0 ... nN-1) ]";
560 io.
data (n_global_elem_at_level[level], buf.str());
565 recv_conn.resize(xfer_buf_sizes[pid]);
567 recv_conn = xfer_conn;
575 for (
auto [elem, recv_conn_iter, n_elem_received] =
576 std::tuple{
xdr_id_type(0), recv_conn.begin(), recv_conn.back()};
577 elem<n_elem_received;
578 elem++, next_global_elem++)
580 output_buffer.clear();
586 output_buffer.push_back(*recv_conn_iter++);
591 output_buffer.push_back(tmp);
594 const xdr_id_type parent_local_id = *recv_conn_iter++;
599 output_buffer.push_back (parent_local_id+processor_offsets[parent_pid]);
602 tmp = *recv_conn_iter++;
603 if (write_partitioning)
604 output_buffer.push_back(tmp);
607 tmp = *recv_conn_iter++;
608 if (write_subdomain_id)
609 output_buffer.push_back(tmp);
612 tmp = *recv_conn_iter++;
614 output_buffer.push_back(tmp);
618 output_buffer.push_back(*recv_conn_iter++);
622 output_buffer.push_back(*recv_conn_iter++);
625 (output_buffer.data(),
626 cast_int<unsigned int>(output_buffer.size()),
627 cast_int<unsigned int>(output_buffer.size()));
635 processor_offsets[0] = processor_offsets.back() + n_elem_on_proc.back();
636 this->
comm().
gather (0, my_n_elem_written_at_level, n_elem_on_proc);
638 processor_offsets[pid] = processor_offsets[pid-1] + n_elem_on_proc[pid-1];
644 std::map<processor_id_type, std::vector<dof_id_type>> requested_ids;
646 for (
const auto & elem :
as_range(
mesh.local_level_elements_begin(level),
647 mesh.local_level_elements_end(level)))
648 if (!child_id_map.count(elem->id()))
650 libmesh_assert_not_equal_to (elem->parent()->processor_id(), this->
processor_id());
653 requested_ids[pid].push_back(elem->id());
656 auto gather_functor =
659 const std::vector<dof_id_type> & ids,
660 std::vector<dof_id_type> & data)
662 const std::size_t ids_size = ids.size();
663 data.resize(ids_size);
666 for (std::size_t i=0; i != ids_size; i++)
669 libmesh_assert_equal_to (child_id_map[ids[i]].first, pid);
671 data[i] = child_id_map[ids[i]].second;
675 auto action_functor =
678 const std::vector<dof_id_type> & ids,
679 const std::vector<dof_id_type> & data)
681 std::size_t data_size = data.size();
683 for (std::size_t i=0; i != data_size; i++)
684 child_id_map[ids[i]] =
685 std::make_pair (pid, data[i]);
690 Parallel::pull_parallel_vector_data
691 (this->
comm(), requested_ids, gather_functor, action_functor, ex);
695 parent_id_map.swap(child_id_map);
696 child_id_map.clear();
699 #endif // LIBMESH_ENABLE_AMR 701 libmesh_assert_equal_to (next_global_elem,
n_elem);
714 std::vector<dof_id_type> xfer_ids;
715 std::vector<Real> xfer_coords;
716 std::vector<Real> & coords=xfer_coords;
718 std::vector<std::vector<dof_id_type>> recv_ids (this->
n_processors());
719 std::vector<std::vector<Real>> recv_coords(this->
n_processors());
722 std::size_t n_written=0;
731 for (std::size_t blk=0, last_node=0; last_node<max_node_id; blk++)
733 const std::size_t first_node = blk*
io_blksize;
734 last_node = std::min((blk+1)*
io_blksize, std::size_t(max_node_id));
736 const std::size_t tot_id_size = last_node - first_node;
742 for (; node_iter != nodes_end; ++node_iter)
744 const Node & node = **node_iter;
745 libmesh_assert_greater_equal(node.
id(), first_node);
746 if (node.
id() >= last_node)
749 xfer_ids.push_back(node.
id());
750 xfer_coords.push_back(node(0));
752 xfer_coords.push_back(node(1));
755 xfer_coords.push_back(node(2));
761 std::vector<std::size_t> ids_size;
763 const std::size_t my_ids_size = xfer_ids.size();
766 this->
comm().
gather (0, my_ids_size, ids_size);
770 std::vector<Parallel::Request>
783 recv_ids[pid].resize(ids_size[pid]);
784 recv_coords[pid].resize(ids_size[pid]*LIBMESH_DIM);
788 recv_ids[0] = xfer_ids;
789 recv_coords[0] = xfer_coords;
794 id_request_handles[pid-1],
797 coord_request_handles[pid-1],
805 this->
comm().
send(0, xfer_ids, id_tag);
806 this->
comm().
send(0, xfer_coords, coord_tag);
816 Parallel::wait (id_request_handles);
817 Parallel::wait (coord_request_handles);
821 libmesh_assert_equal_to(recv_coords[pid].size(),
822 recv_ids[pid].size()*LIBMESH_DIM);
838 coords.resize (3*tot_id_size, std::numeric_limits<Real>::quiet_NaN());
843 libmesh_assert_less_equal(first_node, recv_ids[pid][
idx]);
844 const std::size_t local_idx = recv_ids[pid][
idx] - first_node;
845 libmesh_assert_less(local_idx, tot_id_size);
847 libmesh_assert_less ((3*local_idx+2), coords.size());
848 libmesh_assert_less ((LIBMESH_DIM*
idx+LIBMESH_DIM-1), recv_coords[pid].size());
850 coords[3*local_idx+0] = recv_coords[pid][LIBMESH_DIM*
idx+0];
852 coords[3*local_idx+1] = recv_coords[pid][LIBMESH_DIM*
idx+1];
854 coords[3*local_idx+1] = 0.;
857 coords[3*local_idx+2] = recv_coords[pid][LIBMESH_DIM*
idx+2];
859 coords[3*local_idx+2] = 0.;
867 io.
data_stream (coords.empty() ? nullptr : coords.data(),
868 cast_int<unsigned int>(coords.size()), 3);
873 libmesh_assert_less_equal (n_written, max_node_id);
875 #ifdef LIBMESH_ENABLE_UNIQUE_ID 877 unsigned short write_unique_ids = 1;
879 unsigned short write_unique_ids = 0;
883 io.
data (write_unique_ids,
"# presence of unique ids");
885 #ifdef LIBMESH_ENABLE_UNIQUE_ID 887 std::vector<xdr_id_type> xfer_unique_ids;
888 std::vector<xdr_id_type> & unique_ids=xfer_unique_ids;
889 std::vector<std::vector<xdr_id_type>> recv_unique_ids (this->
n_processors());
897 node_iter =
mesh.local_nodes_begin();
899 for (std::size_t blk=0, last_node=0; last_node<max_node_id; blk++)
901 const std::size_t first_node = blk*
io_blksize;
902 last_node = std::min((blk+1)*
io_blksize, std::size_t(max_node_id));
904 const std::size_t tot_id_size = last_node - first_node;
908 xfer_ids.reserve(tot_id_size);
909 xfer_unique_ids.clear();
910 xfer_unique_ids.reserve(tot_id_size);
912 for (; node_iter != nodes_end; ++node_iter)
914 const Node & node = **node_iter;
915 libmesh_assert_greater_equal(node.
id(), first_node);
916 if (node.
id() >= last_node)
919 xfer_ids.push_back(node.
id());
920 xfer_unique_ids.push_back(node.
unique_id());
925 std::vector<std::size_t> ids_size;
927 const std::size_t my_ids_size = xfer_ids.size();
930 this->
comm().
gather (0, my_ids_size, ids_size);
934 std::vector<Parallel::Request>
947 recv_ids[pid].resize(ids_size[pid]);
948 recv_unique_ids[pid].resize(ids_size[pid]);
952 recv_ids[0] = xfer_ids;
953 recv_unique_ids[0] = xfer_unique_ids;
958 id_request_handles[pid-1],
961 unique_id_request_handles[pid-1],
969 this->
comm().
send(0, xfer_ids, id_tag);
970 this->
comm().
send(0, xfer_unique_ids, unique_id_tag);
980 Parallel::wait (id_request_handles);
981 Parallel::wait (unique_id_request_handles);
985 libmesh_assert_equal_to
986 (recv_ids[pid].size(), recv_unique_ids[pid].size());
989 libmesh_assert_less_equal
990 (tot_id_size, std::min(
io_blksize, std::size_t(max_node_id)));
999 libmesh_assert_less_equal(first_node, recv_ids[pid][
idx]);
1000 const std::size_t local_idx = recv_ids[pid][
idx] - first_node;
1001 libmesh_assert_less (local_idx, unique_ids.size());
1003 unique_ids[local_idx] = recv_unique_ids[pid][
idx];
1010 io.
data_stream (unique_ids.empty() ? nullptr : unique_ids.data(),
1011 cast_int<unsigned int>(unique_ids.size()), 1);
1016 libmesh_assert_less_equal (n_written, max_node_id);
1018 #endif // LIBMESH_ENABLE_UNIQUE_ID 1021 if (n_node_integers)
1029 node_iter =
mesh.local_nodes_begin();
1032 std::vector<dof_id_type> xfer_node_integers;
1033 std::vector<dof_id_type> & node_integers = xfer_node_integers;
1034 std::vector<std::vector<dof_id_type>> recv_node_integers(this->
n_processors());
1036 for (std::size_t blk=0, last_node=0; last_node<max_node_id; blk++)
1038 const std::size_t first_node = blk*
io_blksize;
1039 last_node = std::min((blk+1)*
io_blksize, std::size_t(max_node_id));
1041 const std::size_t tot_id_size = last_node - first_node;
1045 xfer_ids.reserve(tot_id_size);
1046 xfer_node_integers.clear();
1047 xfer_node_integers.reserve(tot_id_size * n_node_integers);
1049 for (; node_iter != nodes_end; ++node_iter)
1051 const Node & node = **node_iter;
1052 libmesh_assert_greater_equal(node.
id(), first_node);
1053 if (node.
id() >= last_node)
1056 xfer_ids.push_back(node.
id());
1059 for (
unsigned int i=0; i != n_node_integers; ++i)
1065 std::vector<std::size_t> ids_size;
1067 const std::size_t my_ids_size = xfer_ids.size();
1070 this->
comm().
gather (0, my_ids_size, ids_size);
1074 std::vector<Parallel::Request>
1087 recv_ids[pid].resize(ids_size[pid]);
1088 recv_node_integers[pid].resize(n_node_integers * ids_size[pid]);
1092 recv_ids[0] = xfer_ids;
1093 recv_node_integers[0] = xfer_node_integers;
1098 id_request_handles[pid-1],
1100 this->
comm().
receive (pid, recv_node_integers[pid],
1101 node_integers_request_handles[pid-1],
1109 this->
comm().
send(0, xfer_ids, id_tag);
1110 this->
comm().
send(0, xfer_node_integers, node_integers_tag);
1120 Parallel::wait (id_request_handles);
1121 Parallel::wait (node_integers_request_handles);
1125 libmesh_assert_equal_to
1126 (recv_ids[pid].size(), recv_node_integers[pid].size() / n_node_integers);
1129 libmesh_assert_less_equal
1130 (tot_id_size, std::min(
io_blksize, std::size_t(max_node_id)));
1145 node_integers.clear();
1146 node_integers.resize (n_node_integers*tot_id_size, static_cast<dof_id_type>(-1));
1151 libmesh_assert_less_equal(first_node, recv_ids[pid][
idx]);
1152 const std::size_t local_idx = recv_ids[pid][
idx] - first_node;
1155 libmesh_assert_less (local_idx, tot_id_size);
1157 for (
unsigned int i=0; i != n_node_integers; ++i)
1158 node_integers[n_node_integers*local_idx + i] = recv_node_integers[pid][n_node_integers*
idx + i];
1165 io.
data_stream (node_integers.empty() ? nullptr : node_integers.data(),
1166 cast_int<unsigned int>(node_integers.size()), n_node_integers);
1171 libmesh_assert_less_equal (n_written, max_node_id);
1194 std::stringstream comment_string;
1195 comment_string <<
"# number of " << bc_type <<
" boundary conditions";
1196 io.
data (n_bcs_out, comment_string.str());
1202 std::vector<xdr_id_type> xfer_bcs, recv_bcs;
1203 std::vector<std::size_t> bc_sizes(this->
n_processors());
1206 std::vector<boundary_id_type> bc_ids;
1210 for (
const auto & elem :
as_range(
mesh.local_level_elements_begin(0),
1211 mesh.local_level_elements_end(0)))
1213 if (bc_type ==
"side")
1215 for (
auto s : elem->side_index_range())
1218 for (
const auto & bc_id : bc_ids)
1221 xfer_bcs.push_back (n_local_level_0_elem);
1222 xfer_bcs.push_back (s) ;
1223 xfer_bcs.push_back (bc_id);
1227 else if (bc_type ==
"edge")
1229 for (
auto e : elem->edge_index_range())
1232 for (
const auto & bc_id : bc_ids)
1235 xfer_bcs.push_back (n_local_level_0_elem);
1236 xfer_bcs.push_back (e) ;
1237 xfer_bcs.push_back (bc_id);
1241 else if (bc_type ==
"shellface")
1243 for (
unsigned short sf=0; sf<2; sf++)
1246 for (
const auto & bc_id : bc_ids)
1249 xfer_bcs.push_back (n_local_level_0_elem);
1250 xfer_bcs.push_back (sf) ;
1251 xfer_bcs.push_back (bc_id);
1257 libmesh_error_msg(
"bc_type not recognized: " + bc_type);
1261 n_local_level_0_elem++;
1264 xfer_bcs.push_back(n_local_level_0_elem);
1265 std::size_t my_size = xfer_bcs.size();
1275 recv_bcs.resize(bc_sizes[pid]);
1277 recv_bcs = xfer_bcs;
1282 = cast_int<dof_id_type>(recv_bcs.back());
1283 recv_bcs.pop_back();
1285 for (std::size_t
idx=0, rbs=recv_bcs.size();
idx<rbs;
idx += 3, n_bcs_out++)
1286 recv_bcs[
idx+0] += elem_offset;
1288 io.
data_stream (recv_bcs.empty() ? nullptr : recv_bcs.data(),
1289 cast_int<unsigned int>(recv_bcs.size()), 3);
1290 elem_offset += my_n_local_level_0_elem;
1292 libmesh_assert_equal_to (n_bcs, n_bcs_out);
1336 io.
data (n_nodesets_out,
"# number of nodesets");
1339 if (!n_nodesets)
return;
1341 std::vector<xdr_id_type> xfer_bcs, recv_bcs;
1342 std::vector<std::size_t> bc_sizes(this->
n_processors());
1345 std::vector<boundary_id_type> nodeset_ids;
1348 for (
const auto & node :
mesh.local_node_ptr_range())
1351 for (
const auto & bc_id : nodeset_ids)
1354 xfer_bcs.push_back (node->id());
1355 xfer_bcs.push_back (bc_id);
1359 xfer_bcs.push_back(n_node);
1360 std::size_t my_size = xfer_bcs.size();
1370 recv_bcs.resize(bc_sizes[pid]);
1372 recv_bcs = xfer_bcs;
1377 cast_int<dof_id_type>(recv_bcs.back());
1378 recv_bcs.pop_back();
1380 for (std::size_t
idx=0, rbs=recv_bcs.size();
idx<rbs;
idx += 2, n_nodesets_out++)
1381 recv_bcs[
idx+0] += node_offset;
1383 io.
data_stream (recv_bcs.empty() ? nullptr : recv_bcs.data(),
1384 cast_int<unsigned int>(recv_bcs.size()), 2);
1385 node_offset += my_n_node;
1387 libmesh_assert_equal_to (n_nodesets, n_nodesets_out);
1399 const std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
1400 info.get_sideset_name_map() :
info.get_nodeset_name_map();
1402 std::vector<new_header_id_type> boundary_ids;
1403 boundary_ids.reserve(boundary_map.size());
1405 std::vector<std::string> boundary_names;
1406 boundary_names.reserve(boundary_map.size());
1412 for (
const auto & [bndry_id,
name] : boundary_map)
1416 boundary_ids.push_back(bndry_id);
1417 boundary_names.push_back(
name);
1421 io.
data(n_boundary_names,
"# sideset id to name map");
1423 io.
data(n_boundary_names,
"# nodeset id to name map");
1425 if (n_boundary_names)
1427 io.
data(boundary_ids);
1428 io.
data(boundary_names);
1437 LOG_SCOPE(
"read()",
"XdrIO");
1457 libmesh_error_msg_if(this->
legacy(),
"We no longer support reading files in the legacy format.");
1461 const unsigned int n_header_metadata_values = 13;
1462 std::vector<new_header_id_type> meta_data(n_header_metadata_values,
sizeof(
xdr_id_type));
1471 std::vector<old_header_id_type> old_data(n_header_metadata_values,
sizeof(
xdr_id_type));
1475 meta_data.assign(old_data.begin(), old_data.end());
1503 uint32_t type_size = 0;
1532 uint64_t type_size = 0;
1566 template <
typename T>
1569 LOG_SCOPE(
"read_header()",
"XdrIO");
1576 std::vector<std::string> node_integer_names;
1577 std::vector<std::string> elem_integer_names;
1578 std::vector<dof_id_type> elemset_codes;
1579 std::vector<std::vector<dof_id_type>> elemset_id_vecs;
1583 io.
data (meta_data[0]);
1584 io.
data (meta_data[1]);
1593 libmesh_assert_greater_equal(meta_data.size(), 10);
1595 io.
data (meta_data[2],
"# type size");
1596 io.
data (meta_data[3],
"# uid size");
1597 io.
data (meta_data[4],
"# pid size");
1598 io.
data (meta_data[5],
"# sid size");
1599 io.
data (meta_data[6],
"# p-level size");
1601 io.
data (meta_data[7],
"# eid size");
1602 io.
data (meta_data[8],
"# side size");
1603 io.
data (meta_data[9],
"# bid size");
1609 libmesh_assert_greater_equal(meta_data.size(), 13);
1611 io.
data (meta_data[10],
"# extra integer size");
1614 io.
data(node_integer_names,
"# node integer names");
1615 meta_data[11] = node_integer_names.size();
1618 io.
data(elem_integer_names,
"# elem integer names");
1619 meta_data[12] = elem_integer_names.size();
1622 io.
data(elemset_codes,
"# elemset codes");
1625 elemset_id_vecs.resize(elemset_codes.size());
1627 io.
data(elemset_id_vecs[i]);
1645 const T &
n_elem = meta_data[0];
1646 const T &
n_nodes = meta_data[1];
1674 elemset_id_vecs[i].end()));
1683 if (read_entity_info)
1688 std::vector<new_header_id_type> subdomain_ids;
1689 std::vector<std::string> subdomain_names;
1694 if (use_new_header_type)
1695 io.
data(n_subdomain_names);
1700 n_subdomain_names = temp;
1703 subdomain_ids.resize(n_subdomain_names);
1704 subdomain_names.resize(n_subdomain_names);
1706 if (n_subdomain_names)
1708 if (use_new_header_type)
1709 io.
data(subdomain_ids);
1712 std::vector<old_header_id_type> temp;
1714 subdomain_ids.assign(temp.begin(), temp.end());
1717 io.
data(subdomain_names);
1723 if (n_subdomain_names == 0)
1726 subdomain_ids.resize(n_subdomain_names);
1727 subdomain_names.resize(n_subdomain_names);
1734 for (
unsigned int i=0; i<n_subdomain_names; ++i)
1735 subdomain_map.emplace(subdomain_ids[i], subdomain_names[i]);
1740 template <
typename T>
1744 const std::vector<new_header_id_type> & meta_data,
1763 std::vector<T> conn, input_buffer(100 );
1768 const size_t unique_id_size_index = 3;
1770 const bool read_unique_id =
1772 meta_data[unique_id_size_index];
1775 const std::size_t n_elem_integers_index = 12;
1779 libmesh_assert_greater_equal(meta_data.size(), 13);
1780 n_elem_integers = meta_data[n_elem_integers_index];
1783 T n_elem_at_level=0, n_processed_at_level=0;
1784 for (
dof_id_type blk=0, first_elem=0, last_elem=0;
1787 first_elem = cast_int<dof_id_type>(blk*
io_blksize);
1788 last_elem = cast_int<dof_id_type>(std::min(cast_int<std::size_t>((blk+1)*
io_blksize),
1789 cast_int<std::size_t>(
n_elem)));
1794 for (
dof_id_type e=first_elem; e<last_elem; e++, n_processed_at_level++)
1796 if (n_processed_at_level == n_elem_at_level)
1799 io.
data (n_elem_at_level);
1800 n_processed_at_level = 0;
1805 unsigned int pos = 0;
1820 input_buffer[pos++] =
static_cast<T
>(-1);
1823 if (read_partitioning)
1826 input_buffer[pos++] = 0;
1829 if (read_subdomain_id)
1832 input_buffer[pos++] = 0;
1838 input_buffer[pos++] = 0;
1842 libmesh_not_implemented();
1845 libmesh_assert_less (pos+n_nodes0, input_buffer.size());
1852 libmesh_assert_less (pos + n_elem_integers, input_buffer.size());
1853 io.
data_stream (&input_buffer[pos], n_elem_integers);
1856 pos += n_elem_integers;
1859 conn.insert (conn.end(), input_buffer.begin(), input_buffer.begin() + pos);
1862 std::size_t conn_size = conn.size();
1864 conn.resize (conn_size);
1868 for (
auto [e, it] = std::tuple{first_elem, conn.begin()}; e<last_elem; e++)
1875 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1886 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1887 unique_id = cast_int<unique_id_type>(tmp);
1896 cast_int<processor_id_type>(*it++);
1899 cast_int<subdomain_id_type>(*it++);
1902 #ifdef LIBMESH_ENABLE_AMR 1903 const unsigned int p_level = cast_int<unsigned int>(tmp);
1912 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1913 elem->set_unique_id(unique_id);
1915 elem->processor_id() = proc_id;
1916 elem->subdomain_id() = subdomain_id;
1917 #ifdef LIBMESH_ENABLE_AMR 1918 elem->hack_p_level(p_level);
1922 parent->add_child(elem.get());
1929 for (
unsigned int n=0, n_n = elem->n_nodes(); n != n_n;
1933 cast_int<dof_id_type>(*it);
1938 elem->set_node(n, node);
1942 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1944 new_node->set_unique_id(
n_elem + global_node_number);
1961 for (
unsigned int ei=0; ei<n_elem_integers; ++ei)
1963 auto extra_int = cast_int<dof_id_type>(*it++);
1970 for (
unsigned char i=0; i!=4; ++i)
1976 "Cannot open dimension " 1978 <<
" mesh file when configured without " 1989 const std::vector<new_header_id_type> & meta_data)
2010 std::vector<dof_id_type> needed_nodes;
2013 for (
auto & node :
mesh.node_ptr_range())
2014 needed_nodes.push_back(node->id());
2016 std::sort (needed_nodes.begin(), needed_nodes.end());
2019 libmesh_assert (std::unique(needed_nodes.begin(), needed_nodes.end()) == needed_nodes.end());
2023 const std::size_t n_node_integers_index = 11;
2027 libmesh_assert_greater_equal(meta_data.size(), 13);
2028 n_node_integers = meta_data[n_node_integers_index];
2032 std::vector<Real> coords;
2033 std::pair<std::vector<dof_id_type>::iterator,
2034 std::vector<dof_id_type>::iterator> pos;
2035 pos.first = needed_nodes.begin();
2038 for (std::size_t blk=0, first_node=0, last_node=0; last_node<
n_nodes; blk++)
2043 coords.resize(3*(last_node - first_node));
2046 io.
data_stream (coords.empty() ? nullptr : coords.data(),
2047 cast_int<unsigned int>(coords.size()));
2054 for (std::size_t n=first_node,
idx=0; n<last_node; n++,
idx+=3)
2059 pos = std::equal_range (pos.first, needed_nodes.end(), n);
2061 if (pos.first != pos.second)
2063 libmesh_assert_equal_to (*pos.first, n);
2077 unsigned short read_unique_ids =
false;
2082 io.
data (read_unique_ids);
2091 if (!read_unique_ids)
2093 #ifdef LIBMESH_ENABLE_UNIQUE_ID 2095 for (
auto & elem :
mesh.element_ptr_range())
2096 max_elem_unique_id = std::max(max_elem_unique_id,
2097 elem->unique_id()+1);
2100 for (
auto & node :
mesh.node_ptr_range())
2101 node->set_unique_id(max_elem_unique_id + node->id());
2108 std::vector<uint32_t> unique_32;
2109 std::vector<uint64_t> unique_64;
2112 pos.first = needed_nodes.begin();
2114 for (std::size_t blk=0, first_node=0, last_node=0; last_node<
n_nodes; blk++)
2122 unique_64.resize(last_node - first_node);
2124 unique_32.resize(last_node - first_node);
2129 io.
data_stream (unique_64.empty() ? nullptr : unique_64.data(),
2130 cast_int<unsigned int>(unique_64.size()));
2132 io.
data_stream (unique_32.empty() ? nullptr : unique_32.data(),
2133 cast_int<unsigned int>(unique_32.size()));
2136 #ifdef LIBMESH_ENABLE_UNIQUE_ID 2142 for (std::size_t n=first_node,
idx=0; n<last_node; n++,
idx++)
2147 pos = std::equal_range (pos.first, needed_nodes.end(), n);
2149 if (pos.first != pos.second)
2151 libmesh_assert_equal_to (*pos.first, n);
2158 #endif // LIBMESH_ENABLE_UNIQUE_ID 2166 if (n_node_integers)
2168 std::vector<dof_id_type> extra_integers;
2171 pos.first = needed_nodes.begin();
2173 for (std::size_t blk=0, first_node=0, last_node=0; last_node<
n_nodes; blk++)
2178 extra_integers.resize((last_node - first_node) * n_node_integers);
2182 io.
data_stream (extra_integers.empty() ? nullptr : extra_integers.data(),
2183 cast_int<unsigned int>(extra_integers.size()));
2188 for (std::size_t n=first_node,
idx=0; n<last_node; n++,
idx++)
2193 pos = std::equal_range (pos.first, needed_nodes.end(), n);
2195 if (pos.first != pos.second)
2197 libmesh_assert_equal_to (*pos.first, n);
2200 for (
unsigned int i=0; i != n_node_integers; ++i)
2210 template <
typename T>
2226 std::vector<T> input_buffer;
2242 for (std::size_t blk=0, first_bc=0, last_bc=0; last_bc<n_bcs; blk++)
2245 last_bc = std::min((blk+1)*
io_blksize, std::size_t(n_bcs));
2247 input_buffer.resize (3*(last_bc - first_bc));
2250 io.
data_stream (input_buffer.empty() ? nullptr : input_buffer.data(),
2251 cast_int<unsigned int>(input_buffer.size()));
2260 for (std::size_t
idx=0, ibs=input_buffer.size();
idx<ibs;
idx+=3)
2263 cast_int<dof_id_type>(input_buffer[
idx+0]);
2264 const unsigned short side =
2265 cast_int<unsigned short>(input_buffer[
idx+1]);
2267 cast_int<boundary_id_type>(input_buffer[
idx+2]);
2273 if (bc_type ==
"side")
2275 libmesh_assert_less (side, elem->n_sides());
2276 boundary_info.
add_side (elem, side, bc_id);
2278 else if (bc_type ==
"edge")
2280 libmesh_assert_less (side, elem->n_edges());
2281 boundary_info.
add_edge (elem, side, bc_id);
2283 else if (bc_type ==
"shellface")
2286 libmesh_assert_less(side, 2);
2292 libmesh_error_msg(
"bc_type not recognized: " + bc_type);
2295 input_buffer.clear();
2301 template <
typename T>
2309 template <
typename T>
2317 template <
typename T>
2325 template <
typename T>
2341 std::vector<T> input_buffer;
2347 io.
data (n_nodesets);
2357 for (std::size_t blk=0, first_bc=0, last_bc=0; last_bc<n_nodesets; blk++)
2360 last_bc = std::min((blk+1)*
io_blksize, std::size_t(n_nodesets));
2362 input_buffer.resize (2*(last_bc - first_bc));
2365 io.
data_stream (input_buffer.empty() ? nullptr : input_buffer.data(),
2366 cast_int<unsigned int>(input_buffer.size()));
2373 for (std::size_t
idx=0, ibs=input_buffer.size();
idx<ibs;
idx+=2)
2376 cast_int<dof_id_type>(input_buffer[
idx+0]);
2378 cast_int<boundary_id_type>(input_buffer[
idx+1]);
2382 boundary_info.
add_node (node, bc_id);
2384 input_buffer.clear();
2394 if (read_entity_info)
2397 std::vector<new_header_id_type> boundary_ids;
2398 std::vector<std::string> boundary_names;
2403 if (use_new_header_type)
2404 io.
data(n_boundary_names);
2409 n_boundary_names = temp;
2412 boundary_names.resize(n_boundary_names);
2414 if (n_boundary_names)
2416 if (use_new_header_type)
2417 io.
data(boundary_ids);
2420 std::vector<old_header_id_type> temp(n_boundary_names);
2422 boundary_ids.assign(temp.begin(), temp.end());
2424 io.
data(boundary_names);
2430 if (n_boundary_names == 0)
2433 boundary_ids.resize(n_boundary_names);
2434 boundary_names.resize(n_boundary_names);
2439 std::map<boundary_id_type, std::string> & boundary_map = is_sideset ?
2440 info.set_sideset_name_map() :
info.set_nodeset_name_map();
2442 for (
unsigned int i=0; i<n_boundary_names; ++i)
2443 boundary_map.emplace(cast_int<boundary_id_type>(boundary_ids[i]), boundary_names[i]);
2458 conn.push_back(elem->
n_nodes());
2460 conn.push_back (elem->
type());
2469 conn.push_back (parent_id);
2471 conn.push_back (parent_pid);
2477 #ifdef LIBMESH_ENABLE_AMR 2478 conn.push_back (elem->
p_level());
2482 conn.push_back (elem->
node_id(n));
2485 for (
unsigned int i=0; i != n_elem_integers; ++i)
2492 (this->
version().find(
"0.9.2") != std::string::npos) ||
2493 (this->
version().find(
"0.9.6") != std::string::npos) ||
2494 (this->
version().find(
"1.1.0") != std::string::npos) ||
2495 (this->
version().find(
"1.3.0") != std::string::npos) ||
2496 (this->
version().find(
"1.8.0") != std::string::npos);
2502 (this->
version().find(
"0.9.6") != std::string::npos) ||
2503 (this->
version().find(
"1.1.0") != std::string::npos) ||
2504 (this->
version().find(
"1.3.0") != std::string::npos) ||
2505 (this->
version().find(
"1.8.0") != std::string::npos);
2511 (this->
version().find(
"1.1.0") != std::string::npos) ||
2512 (this->
version().find(
"1.3.0") != std::string::npos) ||
2513 (this->
version().find(
"1.8.0") != std::string::npos);
2519 (this->
version().find(
"1.3.0") != std::string::npos) ||
2520 (this->
version().find(
"1.8.0") != std::string::npos);
2526 (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