25 #include "libmesh/nemesis_io_helper.h" 27 #include "libmesh/boundary_info.h" 28 #include "libmesh/dof_map.h" 29 #include "libmesh/elem.h" 30 #include "libmesh/equation_systems.h" 31 #include "libmesh/fe_interface.h" 32 #include "libmesh/int_range.h" 33 #include "libmesh/mesh_base.h" 34 #include "libmesh/node.h" 35 #include "libmesh/numeric_vector.h" 36 #include "libmesh/parallel.h" 37 #include "libmesh/utility.h" 39 #if defined(LIBMESH_HAVE_NEMESIS_API) && defined(LIBMESH_HAVE_EXODUS_API) 41 #include <libmesh/ignore_warnings.h> 47 #include <libmesh/restore_warnings.h> 59 bool verbose_in,
bool single_precision) :
64 num_elem_blks_global(0),
65 num_node_sets_global(0),
66 num_side_sets_global(0),
70 num_internal_nodes(0),
72 num_external_nodes(0),
73 num_internal_elems(0),
77 write_complex_abs(true)
80 libmesh_experimental();
92 EX_EXCEPTIONLESS_CHECK_ERR(
ex_err,
"Error flushing buffers to file.");
110 EX_CHECK_ERR(
ex_err,
"Error retrieving nodeset parameters.");
111 message(
"Parameters retrieved successfully for nodeset: ",
id);
125 EX_CHECK_ERR(
ex_err,
"Error retrieving nodeset data.");
126 message(
"Data retrieved successfully for nodeset: ",
id);
135 Nemesis::ne_get_init_global(
ex_id,
167 Nemesis::ne_get_ss_param_global(
ex_id,
175 libMesh::out <<
"[" << this->
processor_id() <<
"] " <<
"Global Sideset IDs, Side Counts, and DF counts:" << std::endl;
200 Nemesis::ne_get_ns_param_global(
ex_id,
208 libMesh::out <<
"[" << this->
processor_id() <<
"] " <<
"Global Nodeset IDs, Node Counts, and DF counts:" << std::endl;
231 Nemesis::ne_get_eb_info_global(
ex_id,
255 Nemesis::ne_get_init_info(
ex_id,
274 Nemesis::ne_get_loadbal_param(
ex_id,
307 Nemesis::ne_get_elem_map(
ex_id,
339 Nemesis::ne_get_node_map(
ex_id,
377 Nemesis::ne_get_cmap_params(
ex_id,
427 Nemesis::ne_get_node_cmap(
ex_id,
432 EX_CHECK_ERR(
nemesis_err_flag,
"Error reading node cmap node and processor ids!");
469 Nemesis::ne_get_elem_cmap(
ex_id,
475 EX_CHECK_ERR(
nemesis_err_flag,
"Error reading elem cmap elem, side, and processor ids!");
506 unsigned num_proc_in_file_in,
507 const char * ftype_in)
510 Nemesis::ne_put_init_info(
ex_id,
513 const_cast<char *>(ftype_in));
523 unsigned num_elem_blks_global_in,
524 unsigned num_node_sets_global_in,
525 unsigned num_side_sets_global_in)
528 Nemesis::ne_put_init_global(
ex_id,
531 num_elem_blks_global_in,
532 num_node_sets_global_in,
533 num_side_sets_global_in);
541 std::vector<int> & global_elem_blk_cnts_in)
544 Nemesis::ne_put_eb_info_global(
ex_id,
545 global_elem_blk_ids_in.data(),
546 global_elem_blk_cnts_in.data());
548 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing global element block information!");
555 std::vector<int> & num_global_node_counts_in,
556 std::vector<int> & num_global_node_df_counts_in)
562 Nemesis::ne_put_ns_param_global(
ex_id,
563 global_nodeset_ids_in.data(),
564 num_global_node_counts_in.data(),
565 num_global_node_df_counts_in.data());
575 std::vector<int> & num_global_side_counts_in,
576 std::vector<int> & num_global_side_df_counts_in)
582 Nemesis::ne_put_ss_param_global(
ex_id,
583 global_sideset_ids_in.data(),
584 num_global_side_counts_in.data(),
585 num_global_side_df_counts_in.data());
595 unsigned num_border_nodes_in,
596 unsigned num_external_nodes_in,
597 unsigned num_internal_elems_in,
598 unsigned num_border_elems_in,
599 unsigned num_node_cmaps_in,
600 unsigned num_elem_cmaps_in)
603 Nemesis::ne_put_loadbal_param(
ex_id,
604 num_internal_nodes_in,
606 num_external_nodes_in,
607 num_internal_elems_in,
621 std::vector<int> & node_cmap_node_cnts_in,
622 std::vector<int> & elem_cmap_ids_in,
623 std::vector<int> & elem_cmap_elem_cnts_in)
626 Nemesis::ne_put_cmap_params(
ex_id,
627 node_cmap_ids_in.empty() ? nullptr : node_cmap_ids_in.data(),
628 node_cmap_node_cnts_in.empty() ? nullptr : node_cmap_node_cnts_in.data(),
629 elem_cmap_ids_in.empty() ? nullptr : elem_cmap_ids_in.data(),
630 elem_cmap_elem_cnts_in.empty() ? nullptr : elem_cmap_elem_cnts_in.data(),
640 std::vector<std::vector<int>> & node_cmap_proc_ids_in)
650 for (
const auto & node_id : node_cmap_node_ids_in[i])
658 for (
const auto & proc_id : node_cmap_proc_ids_in[i])
666 int * node_ids_ptr = node_cmap_node_ids_in[i].empty() ?
667 nullptr : node_cmap_node_ids_in[i].data();
668 int * proc_ids_ptr = node_cmap_proc_ids_in[i].empty() ?
669 nullptr : node_cmap_proc_ids_in[i].data();
673 node_ids_ptr, proc_ids_ptr,
676 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing node communication map to file!");
684 std::vector<int> & node_mapb_in,
685 std::vector<int> & node_mape_in)
688 Nemesis::ne_put_node_map(
ex_id,
689 node_mapi_in.empty() ? nullptr : node_mapi_in.data(),
690 node_mapb_in.empty() ? nullptr : node_mapb_in.data(),
691 node_mape_in.empty() ? nullptr : node_mape_in.data(),
694 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing Nemesis internal and border node maps to file!");
701 std::vector<std::vector<int>> & elem_cmap_side_ids_in,
702 std::vector<std::vector<int>> & elem_cmap_proc_ids_in)
707 Nemesis::ne_put_elem_cmap(
ex_id,
709 elem_cmap_elem_ids_in[i].data(),
710 elem_cmap_side_ids_in[i].data(),
711 elem_cmap_proc_ids_in[i].data(),
714 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing elem communication map to file!");
722 std::vector<int> & elem_mapb_in)
725 Nemesis::ne_put_elem_map(
ex_id,
726 elem_mapi_in.empty() ? nullptr : elem_mapi_in.data(),
727 elem_mapb_in.empty() ? nullptr : elem_mapb_in.data(),
730 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing Nemesis internal and border element maps to file!");
901 const std::string & title_in)
904 pmesh.active_local_elements_end()));
926 EX_CHECK_ERR(
ex_err,
"Error initializing new Nemesis file.");
975 for (; it != end; ++it)
978 libmesh_assert_equal_to (static_cast<unsigned>(this->
elem_cmap_ids[cnt]), it->first);
981 std::set<std::pair<unsigned,unsigned>> & elem_set = it->second;
988 std::set<std::pair<unsigned,unsigned>>::iterator elem_set_iter = elem_set.begin();
991 for (std::size_t j=0, eceis=this->
elem_cmap_elem_ids[cnt].size(); j<eceis; ++j, ++elem_set_iter)
1044 libmesh_assert_less_equal
1057 for (; it != end; ++it)
1060 libmesh_assert_equal_to (static_cast<unsigned>(this->
node_cmap_ids[cnt]), it->first);
1063 std::set<unsigned> &
node_set = it->second;
1069 std::set<unsigned>::iterator node_set_iter =
node_set.begin();
1072 for (std::size_t j=0, nceis=this->
node_cmap_node_ids[cnt].size(); j<nceis; ++j, ++node_set_iter)
1100 for (
const auto & proc_id : id_vec)
1126 for (; it != end; ++it)
1161 for (; it != end; ++it)
1193 std::set<unsigned> all_elem_ids;
1198 std::set<unsigned> neighboring_processor_ids;
1200 for (
const auto & elem : pmesh.active_local_element_ptr_range())
1205 all_elem_ids.insert(elem->id());
1208 bool is_border_elem =
false;
1224 for (
auto node : elem->node_index_range())
1228 for (
auto n : elem->side_index_range())
1230 if (elem->neighbor_ptr(n) !=
nullptr)
1232 unsigned neighbor_proc_id = elem->neighbor_ptr(n)->processor_id();
1238 is_border_elem =
true;
1239 neighboring_processor_ids.insert(neighbor_proc_id);
1242 unsigned nemesis_side_id = conv.get_inverse_side_map(n);
1247 <<
" mapped to (1-based) Exodus side " 1267 std::set_difference(all_elem_ids.begin(), all_elem_ids.end(),
1279 for (
const auto &
id : neighboring_processor_ids)
1286 cast_int<int>(neighboring_processor_ids.size());
1290 <<
"Number of neighboring processor IDs=" 1301 << proc_id <<
" communicates " 1302 <<
set.size() <<
" elements." << std::endl;
1329 std::set<boundary_id_type> global_side_boundary_ids
1338 cast_int<int>(global_side_boundary_ids.size());
1343 global_side_boundary_ids.begin(),
1344 global_side_boundary_ids.end());
1356 typedef std::tuple<dof_id_type, unsigned short int, boundary_id_type> Tuple;
1360 std::vector<Tuple>::iterator
1361 it = bc_triples.begin(),
1362 new_end = bc_triples.end();
1364 while (it != new_end)
1372 std::swap (*it, *new_end);
1379 bc_triples.erase(new_end, bc_triples.end());
1389 cast_int<int>(std::count_if(bc_triples.begin(),
1391 [id](
const Tuple & t)->
bool {
return std::get<2>(t) ==
id; }));
1421 std::set<boundary_id_type> local_node_boundary_ids;
1424 std::set<boundary_id_type> global_node_boundary_ids
1429 local_node_boundary_ids = global_node_boundary_ids;
1436 cast_int<int>(global_node_boundary_ids.size());
1441 global_node_boundary_ids.begin(),
1442 global_node_boundary_ids.end());
1452 for (
const auto &
id : local_node_boundary_ids)
1460 typedef std::tuple<dof_id_type, boundary_id_type> Tuple;
1466 << bc_tuples.size() << std::endl;
1468 for (
const auto & t : bc_tuples)
1469 libMesh::out <<
"(" << std::get<0>(t) <<
", " << std::get<1>(t) <<
") ";
1484 std::vector<Tuple>::iterator
1485 it = bc_tuples.begin(),
1486 new_end = bc_tuples.end();
1488 while (it != new_end)
1496 std::swap(*it, *new_end);
1503 bc_tuples.erase(new_end, bc_tuples.end());
1510 cast_int<int>(std::count_if(bc_tuples.begin(),
1512 [id](
const Tuple & t)->
bool {
return std::get<1>(t) ==
id; }));
1533 std::set<subdomain_id_type> global_subdomain_ids;
1536 std::map<subdomain_id_type, unsigned> global_subdomain_counts;
1538 for (
const auto & elem : pmesh.active_local_element_ptr_range())
1549 global_subdomain_ids.insert(cur_subdomain);
1552 global_subdomain_counts[cur_subdomain]++;
1560 std::vector<subdomain_id_type> global_subdomain_ids_vector(global_subdomain_ids.begin(),
1561 global_subdomain_ids.end());
1567 global_subdomain_ids.insert(global_subdomain_ids_vector.begin(),
1568 global_subdomain_ids_vector.end());
1573 cast_int<int>(global_subdomain_ids.size());
1579 for (
const auto & [subdomain_id, cnt] : global_subdomain_counts)
1582 <<
static_cast<unsigned>(subdomain_id)
1583 <<
", Count: " << cnt <<
", ";
1595 for (
const auto &
id : global_subdomain_ids)
1612 global_subdomain_ids.begin(),
1613 global_subdomain_ids.end());
1638 pmesh.active_local_elements_end());
1656 <<
"local_subdomain_counts [" <<
static_cast<unsigned>(sbd_id) <<
"]= " 1666 for (
const auto & elem : pmesh.active_local_element_ptr_range())
1669 for (
auto n : elem->node_index_range())
1720 for (
auto & [block_id, elem_ids_this_subdomain] :
subdomain_map)
1725 libmesh_error_msg_if(elem_ids_this_subdomain.size() == 0,
1726 "Error, no element IDs found in subdomain " << block_id);
1741 current_block_connectivity.clear();
1742 current_block_connectivity.resize(elem_ids_this_subdomain.size() * this->
num_nodes_per_elem);
1744 for (
auto i :
index_range(elem_ids_this_subdomain))
1746 auto elem_id = elem_ids_this_subdomain[i];
1776 for (
auto j :
make_range(this->num_nodes_per_elem))
1779 const unsigned int elem_node_index = conv.get_inverse_node_map(j);
1781 current_block_connectivity[connect_index] =
1783 elem.
node_id(elem_node_index));
1802 std::map<unsigned, std::set<unsigned>> proc_nodes_touched;
1810 for (
const auto & elem : pmesh.active_element_ptr_range())
1814 std::set<unsigned> & set_p = proc_nodes_touched[ elem->processor_id() ];
1817 for (
auto node : elem->node_index_range())
1818 set_p.insert(elem->node_id(node));
1824 <<
"] proc_nodes_touched contains " 1825 << proc_nodes_touched.size()
1826 <<
" sets of nodes." 1829 for (
const auto & [proc_id,
set] : proc_nodes_touched)
1831 <<
"] proc_nodes_touched[" << proc_id <<
"] has " 1841 for (
auto & [proc_id, other_set] : proc_nodes_touched)
1847 std::set<unsigned int> this_intersection;
1850 std::set<unsigned> & my_set = proc_nodes_touched[this->
processor_id()];
1852 std::set_intersection(my_set.begin(), my_set.end(),
1853 other_set.begin(), other_set.end(),
1854 std::inserter(this_intersection, this_intersection.end()));
1856 if (!this_intersection.empty())
1858 (proc_id, std::move(this_intersection));
1865 <<
"] this->proc_nodes_touched_intersections[" << proc_id <<
"] has " 1884 std::set<unsigned> & other_set = pr.second;
1885 std::set<unsigned> intermediate_result;
1888 other_set.begin(), other_set.end(),
1889 std::inserter(intermediate_result, intermediate_result.end()));
1895 libmesh_assert_less_equal
1896 (this->proc_nodes_touched_intersections.size(),
1923 std::map<boundary_id_type, std::vector<int>> local_node_boundary_id_lists;
1930 typedef std::tuple<dof_id_type, boundary_id_type> Tuple;
1931 std::vector<Tuple> bc_tuples =
mesh.get_boundary_info().build_node_list();
1936 << bc_tuples.size() << std::endl;
1938 for (
const auto & t : bc_tuples)
1939 libMesh::out <<
"(" << std::get<0>(t) <<
", " << std::get<1>(t) <<
") ";
1946 for (
const auto & t : bc_tuples)
1955 std::vector<int> & current_id_set = local_node_boundary_id_lists[std::get<1>(t)];
1959 current_id_set.push_back( it->second );
1966 for (
const auto & [bndry_id,
set] : local_node_boundary_id_lists)
1971 for (
const auto &
id :
set)
1985 const std::string & current_ns_name =
1986 mesh.get_boundary_info().get_nodeset_name
1987 (cast_int<boundary_id_type>(nodeset_id));
1991 names_table.push_back_entry(current_ns_name);
1996 <<
"] Writing out Exodus nodeset info for ID: " << nodeset_id
1997 <<
", Name: " << current_ns_name
2002 int exodus_id = nodeset_id;
2012 if (
const auto it = local_node_boundary_id_lists.find (cast_int<boundary_id_type>(nodeset_id));
2013 it == local_node_boundary_id_lists.end())
2018 <<
"] No nodeset data for ID: " << nodeset_id
2019 <<
" on this processor." << std::endl;
2022 this->
ex_err = exII::ex_put_node_set_param(this->
ex_id,
2026 EX_CHECK_ERR(this->
ex_err,
"Error writing nodeset parameters in Nemesis");
2032 const std::vector<int> & current_nodeset_ids = it->second;
2035 this->
ex_err = exII::ex_put_node_set_param(this->
ex_id,
2037 current_nodeset_ids.size(),
2040 EX_CHECK_ERR(this->
ex_err,
"Error writing nodeset parameters in Nemesis");
2045 current_nodeset_ids.data());
2047 EX_CHECK_ERR(this->
ex_err,
"Error writing nodesets in Nemesis");
2055 names_table.get_char_star_star());
2056 EX_CHECK_ERR(
ex_err,
"Error writing nodeset names");
2073 std::map<boundary_id_type, std::vector<int>> local_elem_boundary_id_lists;
2074 std::map<boundary_id_type, std::vector<int>> local_elem_boundary_id_side_lists;
2077 std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> bndry_elem_side_id_list =
2078 mesh.get_boundary_info().build_side_list();
2081 for (
const auto & t : bndry_elem_side_id_list)
2084 const Elem * elem =
mesh.elem_ptr(std::get<0>(t));
2086 std::vector<const Elem *> family;
2087 #ifdef LIBMESH_ENABLE_AMR 2094 family.push_back( elem );
2100 for (
const auto & tree_elem : family)
2103 const Elem & f =
mesh.elem_ref(f_id);
2116 local_elem_boundary_id_side_lists[ std::get<2>(t) ].push_back(conv.get_inverse_side_map( std::get<1>(t) ));
2130 const std::string & current_ss_name =
2131 mesh.get_boundary_info().get_sideset_name
2132 (cast_int<boundary_id_type>(exodus_id));
2136 names_table.push_back_entry(current_ss_name);
2141 <<
"] Writing out Exodus sideset info for ID: " << exodus_id
2142 <<
", Name: " << current_ss_name
2147 if (
const auto it = local_elem_boundary_id_lists.find (cast_int<boundary_id_type>(exodus_id));
2148 it == local_elem_boundary_id_lists.end())
2153 <<
"] No sideset data for ID: " << exodus_id
2154 <<
" on this processor." << std::endl;
2157 this->
ex_err = exII::ex_put_side_set_param(this->
ex_id,
2161 EX_CHECK_ERR(this->
ex_err,
"Error writing sideset parameters in Nemesis");
2167 const std::vector<int> & current_sideset_elem_ids = it->second;
2170 std::vector<int> & current_sideset_side_ids =
2171 libmesh_map_find(local_elem_boundary_id_side_lists,
2172 cast_int<boundary_id_type>(exodus_id));
2175 this->
ex_err = exII::ex_put_side_set_param(this->
ex_id,
2177 current_sideset_elem_ids.size(),
2180 EX_CHECK_ERR(this->
ex_err,
"Error writing sideset parameters in Nemesis");
2185 current_sideset_elem_ids.data(),
2186 current_sideset_side_ids.data());
2188 EX_CHECK_ERR(this->
ex_err,
"Error writing sidesets in Nemesis");
2197 names_table.get_char_star_star());
2198 EX_CHECK_ERR(
ex_err,
"Error writing sideset names");
2209 x.resize(local_num_nodes);
2210 y.resize(local_num_nodes);
2211 z.resize(local_num_nodes);
2222 if (local_num_nodes)
2225 ex_err = exII::ex_put_coord
2230 EX_CHECK_ERR(
ex_err,
"Error writing node coordinates");
2234 EX_CHECK_ERR(
ex_err,
"Error writing node num map");
2238 ex_err = exII::ex_put_coord(
ex_id,
nullptr,
nullptr,
nullptr);
2239 EX_CHECK_ERR(
ex_err,
"Error writing empty node coordinates");
2241 ex_err = exII::ex_put_node_num_map(
ex_id,
nullptr);
2242 EX_CHECK_ERR(
ex_err,
"Error writing empty node num map");
2269 (
mesh.subdomain_name(cast_int<subdomain_id_type>(this->global_elem_blk_ids[i])));
2276 this->
ex_err = exII::ex_put_elem_block(this->
ex_id,
2283 EX_CHECK_ERR(this->
ex_err,
"Error writing element block from Nemesis.");
2290 cast_int<subdomain_id_type>(it->first);
2291 const std::vector<int> & this_block_connectivity = it->second;
2292 std::vector<dof_id_type> & elements_in_this_block =
subdomain_map[block];
2305 conv.exodus_elem_type().c_str(),
2306 elements_in_this_block.size(),
2309 EX_CHECK_ERR(
ex_err,
"Error writing element block from Nemesis.");
2313 this_block_connectivity.data());
2314 EX_CHECK_ERR(
ex_err,
"Error writing element connectivities from Nemesis.");
2321 EX_CHECK_ERR(
ex_err,
"Error writing element map");
2325 EX_CHECK_ERR(
ex_err,
"Error writing element block names");
2334 const std::vector<std::string> & names,
2337 int num_vars = cast_int<int>(names.size());
2340 for (
int c=0; c<num_vars; c++)
2342 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 2343 std::vector<Real> real_parts(
num_nodes);
2344 std::vector<Real> imag_parts(
num_nodes);
2345 std::vector<Real> magnitudes(
num_nodes);
2350 real_parts[i] =
value.real();
2351 imag_parts[i] =
value.imag();
2352 magnitudes[i] = std::abs(
value);
2358 std::vector<Number> cur_soln(this->num_nodes);
2372 const std::vector<std::string> & names,
2374 const std::vector<std::string> & output_names)
2376 int num_vars = cast_int<int>(names.size());
2378 for (
int c=0; c<num_vars; c++)
2381 auto pos = std::find(output_names.begin(), output_names.end(), names[c]);
2384 if (pos == output_names.end())
2390 int variable_name_position =
2394 std::vector<numeric_index_type> required_indices(this->
num_nodes);
2401 std::vector<Number> local_soln;
2402 parallel_soln.
localize(local_soln, required_indices);
2404 #ifndef LIBMESH_USE_COMPLEX_NUMBERS 2410 std::vector<Real> real_parts(
num_nodes);
2411 std::vector<Real> imag_parts(
num_nodes);
2412 std::vector<Real> magnitudes(
num_nodes);
2416 real_parts[i] = local_soln[i].real();
2417 imag_parts[i] = local_soln[i].imag();
2418 magnitudes[i] = std::abs(local_soln[i]);
2432 const std::vector<std::pair<unsigned int, unsigned int>> & var_nums,
2434 const std::vector<std::string> & output_names)
2441 for (
auto [sys_num, var] : var_nums)
2446 auto pos = std::find(output_names.begin(), output_names.end(),
name);
2449 if (pos == output_names.end())
2455 int variable_name_position =
2459 std::vector<numeric_index_type> required_indices(this->
num_nodes);
2463 std::vector<Number> local_soln;
2468 std::vector<numeric_index_type> scalar_indices;
2471 required_indices[i] = scalar_indices[0];
2478 bool found_all_indices =
true;
2482 if (node.
n_comp(sys_num, var))
2483 required_indices[i] = node.
dof_number(sys_num, var, 0);
2486 found_all_indices =
false;
2491 if (found_all_indices)
2494 if (!found_all_indices)
2502 std::vector<Number> elem_soln;
2503 std::vector<Number> nodal_soln;
2504 std::vector<dof_id_type> dof_indices;
2506 for (
const auto & elem :
mesh.active_local_element_ptr_range())
2510 elem_soln.resize(dof_indices.size());
2513 elem_soln[i] = sys_soln(dof_indices[i]);
2522 if (!elem->infinite())
2523 for (
auto n : elem->node_index_range())
2525 const std::size_t exodus_num =
2527 libmesh_assert_greater(exodus_num, 0);
2528 libmesh_assert_less(exodus_num-1, local_soln.size());
2529 local_soln[exodus_num-1] = nodal_soln[n];
2535 #ifndef LIBMESH_USE_COMPLEX_NUMBERS 2541 std::vector<Real> real_parts(
num_nodes);
2542 std::vector<Real> imag_parts(
num_nodes);
2543 std::vector<Real> magnitudes(
num_nodes);
2547 real_parts[i] = local_soln[i].real();
2548 imag_parts[i] = local_soln[i].imag();
2549 magnitudes[i] = std::abs(local_soln[i]);
2564 const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
2567 if (names.size() == 0)
2593 if (vars_active_subdomains[var].empty() ||
2595 truth_tab[names.size() * blk + var] = 1;
2598 if (truth_tab.size())
2602 cast_int<int>(names.size()),
2604 EX_CHECK_ERR(
ex_err,
"Error writing element truth table.");
2613 const std::vector<std::pair<unsigned int, unsigned int>> &var_nums,
2615 const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
2625 unsigned int var_ctr = 0;
2628 const unsigned int sys_num = var_nums[v].first;
2629 const unsigned int var = var_nums[v].second;
2636 const unsigned int n_comps =
2640 const auto & active_subdomains = vars_active_subdomains[v];
2645 cast_int<subdomain_id_type>(sbd_id_int);
2647 const std::vector<dof_id_type> empty_vec;
2648 const std::vector<dof_id_type> & elem_ids =
2654 if ((active_subdomains.empty() || active_subdomains.count(sbd_id)) && elem_ids.size())
2656 std::vector<numeric_index_type> required_indices;
2657 required_indices.reserve(elem_ids.size());
2663 libmesh_assert_equal_to(n_comps,
mesh.elem_ref(elem_ids.back()).n_comp(sys_num, var));
2667 for (
unsigned int comp = 0; comp < n_comps; ++comp)
2669 for (
const auto &
id : elem_ids)
2670 required_indices.push_back(
mesh.elem_ref(
id).dof_number(sys_num, var, comp));
2672 std::vector<Number> local_soln;
2676 required_indices.clear();
2683 if (local_soln.size())
2685 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 2687 std::vector<Real> local_soln_buffer(local_soln.size());
2688 std::transform(local_soln.begin(), local_soln.end(),
2689 local_soln_buffer.begin(), [](
Number n) {
return n.real(); });
2692 static_cast<int>(stride*(var_ctr+comp)+1),
2693 static_cast<int>(sbd_id),
2694 static_cast<int>(local_soln.size()),
2696 EX_CHECK_ERR(
ex_err,
"Error writing element real values.");
2698 std::transform(local_soln.begin(), local_soln.end(),
2699 local_soln_buffer.begin(), [](
Number n) {
return n.imag(); });
2702 static_cast<int>(stride*(var_ctr+comp)+2),
2703 static_cast<int>(sbd_id),
2704 static_cast<int>(local_soln.size()),
2706 EX_CHECK_ERR(
ex_err,
"Error writing element imaginary values.");
2710 std::transform(local_soln.begin(), local_soln.end(),
2711 local_soln_buffer.begin(), [](
Number n) {
return std::abs(n); });
2714 static_cast<int>(stride*(var_ctr+comp)+2),
2715 static_cast<int>(sbd_id),
2716 static_cast<int>(local_soln.size()),
2718 EX_CHECK_ERR(
ex_err,
"Error writing element magnitudes.");
2720 #else // LIBMESH_USE_COMPLEX_NUMBERS 2723 static_cast<int>(var_ctr+comp+1),
2724 static_cast<int>(sbd_id),
2725 static_cast<int>(local_soln.size()),
2727 EX_CHECK_ERR(
ex_err,
"Error writing element values.");
2728 #endif // LIBMESH_USE_COMPLEX_NUMBERS 2744 std::vector<std::string> & result)
2755 const std::size_t n_names = result.size();
2760 (n_names ?
nullptr : &n_names));
2762 this->
comm().
min(pid_broadcasting_names);
2774 std::ostringstream file_oss;
2793 unsigned int field_width = cast_int<unsigned int>(file_oss.str().size());
2796 libMesh::out <<
"field_width=" << field_width << std::endl;
2799 file_oss << base_filename
2801 <<
'.' << std::setfill(
'0') << std::setw(field_width) << this->
processor_id();
2804 return file_oss.str();
2809 #endif // #if defined(LIBMESH_HAVE_NEMESIS_API) && defined(LIBMESH_HAVE_EXODUS_API) std::string name(const ElemQuality q)
This function returns a string containing some name for q.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
void write_var_names(ExodusVarType type, const std::vector< std::string > &names)
Wraps calls to exII::ex_put_var_names() and exII::ex_put_var_param().
FEFamily family
The type of finite element.
This class facilitates inline conversion of an input data vector to a different precision level...
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
This is the EquationSystems class.
bool _elem_vars_initialized
const std::set< boundary_id_type > & get_side_boundary_ids() const
Nemesis_IO_Helper(const ParallelObject &parent, bool verbose=false, bool single_precision=false)
Constructor.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
std::map< subdomain_id_type, std::vector< dof_id_type > > subdomain_map
Map of subdomains to element numbers.
virtual ~Nemesis_IO_Helper()
Destructor.
std::vector< std::string > elem_var_names
void active_family_tree_by_side(std::vector< const Elem *> &family, unsigned int side, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to side...
A Node is like a Point, but with more information.
std::vector< int > num_global_node_counts
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
void compute_element_maps()
This function computes element maps (really just packs vectors) which map the elements to internal an...
std::vector< int > global_nodeset_ids
Containers for reading global nodeset information.
virtual void initialize(std::string title, const MeshBase &mesh, bool use_discontinuous=false) override
Specialization of the initialize function from ExodusII_IO_Helper that also writes global initial dat...
unsigned int n_comp(const unsigned int s, const unsigned int var) const
void read_nodeset(int id)
Reading functions.
char ftype
The type of file to be written.
std::vector< int > global_sideset_ids
Containers for reading global sideset (boundary conditions) information.
void compute_num_global_nodesets(const MeshBase &pmesh)
This function uses global communication routines to determine the number of nodesets across the entir...
std::vector< int > node_cmap_ids
Vectors for storing the communication map parameters.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void get_ss_param_global()
Fills: global_sideset_ids, num_global_side_counts, num_global_side_df_counts Call after: get_init_glo...
virtual void read_var_names_impl(const char *var_type, int &count, std::vector< std::string > &result)
read_var_names() dispatches to this function.
int num_external_nodes
The number of FEM nodes that reside on another processor but whose element partially resides on the c...
int nemesis_err_flag
Member data.
std::vector< int > exodus_elem_num_to_libmesh
std::vector< int > node_mape
Vector which stores external node IDs.
void compute_elem_communication_maps()
This function computes element communication maps (really just packs vectors) in preparation for writ...
void compute_num_global_elem_blocks(const MeshBase &pmesh)
This function uses global communication routines to determine the number of element blocks across the...
This is the base class from which all geometric element types are derived.
int num_node_cmaps
The number of nodal communication maps for this processor.
void put_elem_map(std::vector< int > &elem_mapi, std::vector< int > &elem_mapb)
Outputs IDs of internal and border elements.
const Parallel::Communicator & comm() const
std::vector< int > num_global_node_df_counts
std::vector< int > block_ids
std::vector< std::vector< int > > elem_cmap_side_ids
std::vector< std::vector< int > > node_cmap_proc_ids
void put_ns_param_global(std::vector< int > &global_nodeset_ids, std::vector< int > &num_global_node_counts, std::vector< int > &num_global_node_df_counts)
This function writes information about global node sets.
const ExodusII_IO_Helper::Conversion & get_conversion(const ElemType type) const
The libMesh namespace provides an interface to certain functionality in the library.
void put_eb_info_global(std::vector< int > &global_elem_blk_ids, std::vector< int > &global_elem_blk_cnts)
Writes global block information to the file .) global_elem_blk_ids - list of block IDs for all blocks...
std::vector< int > node_list
void compute_border_node_ids(const MeshBase &pmesh)
This function constructs the set of border node IDs present on the current mesh.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
bool write_complex_abs
By default, when complex numbers are enabled, for each variable we write out three values: the real p...
const T_sys & get_system(std::string_view name) const
void compute_communication_map_parameters()
This function determines the communication map parameters which will eventually be written to file...
void write_nodal_values(int var_id, const std::vector< Real > &values, int timestep)
Writes the vector of values to a nodal variable.
void message(std::string_view msg)
Prints the message defined in msg.
void check_existing_vars(ExodusVarType type, std::vector< std::string > &names, std::vector< std::string > &names_from_file)
When appending: during initialization, check that variable names in the file match those you attempt ...
Real distance(const Point &p)
virtual void write_elements(const MeshBase &mesh, bool use_discontinuous=false) override
This function is specialized to write the connectivity.
std::map< dof_id_type, dof_id_type > libmesh_node_num_to_exodus
int num_nodes_global
Global initial information.
void compute_node_communication_maps()
Compute the node communication maps (really just pack vectors) in preparation for writing them to fil...
uint8_t processor_id_type
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn...
std::vector< int > num_global_side_df_counts
This is the MeshBase class.
void close() noexcept
Closes the ExodusII mesh file.
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of element numbers, sides, and ids for those sides.
void write_element_values(const MeshBase &mesh, const EquationSystems &es, const std::vector< std::pair< unsigned int, unsigned int >> &var_nums, int timestep, const std::vector< std::set< subdomain_id_type >> &vars_active_subdomains)
Writes the vector of elemental variable values, one variable and one subdomain at a time...
bool _use_mesh_dimension_instead_of_spatial_dimension
const std::set< boundary_id_type > & get_node_boundary_ids() const
void build_element_and_node_maps(const MeshBase &pmesh)
This function builds the libmesh -> exodus and exodus -> libmesh node and element maps...
void put_init_global(dof_id_type num_nodes_global, dof_id_type num_elems_global, unsigned num_elem_blks_global, unsigned num_node_sets_global, unsigned num_side_sets_global)
Writes global information including: .) global number of nodes .) global number of elems ...
This class handles the numbering of degrees of freedom on a mesh.
processor_id_type n_processors() const
void build_node_list(std::vector< dof_id_type > &node_id_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of nodes and ids for those nodes.
const dof_id_type n_nodes
virtual void write_nodal_coordinates(const MeshBase &mesh, bool use_discontinuous=false) override
This function is specialized from ExodusII_IO_Helper to write only the nodal coordinates stored on th...
std::vector< int > num_global_side_counts
This class defines the notion of a variable in the system.
std::vector< int > nodeset_ids
void update()
Uses ex_update() to flush buffers to file.
void push_back_entry(const std::string &name)
Adds another name to the current data table.
void min(const T &r, T &o, Request &req) const
virtual unsigned int n_nodes() const =0
std::vector< int > global_elem_blk_ids
Read the global element block IDs and counts.
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
virtual void initialize_element_variables(std::vector< std::string > names, const std::vector< std::set< subdomain_id_type >> &vars_active_subdomains) override
Override the Exodus Helper's implementation of this function so that it works correctly in parallel...
std::vector< std::vector< int > > elem_cmap_elem_ids
3 vectors of vectors for storing element communication IDs for this processor.
std::set< unsigned > border_elem_ids
A set of border elem IDs for this processor.
Manages consistently variables, degrees of freedom, and coefficient vectors.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
std::set< unsigned > internal_node_ids
A set of internal node IDs for this processor.
std::vector< int > node_mapi
Vector which stores internal node IDs.
int num_proc
The number of processors for which the NEMESIS I file was created.
std::string construct_nemesis_filename(std::string_view base_filename)
Given base_filename, foo.e, constructs the Nemesis filename foo.e.X.Y, where X=n. ...
const std::string & variable_name(const unsigned int i) const
This is the ExodusII_IO_Helper class.
std::vector< std::vector< int > > elem_cmap_proc_ids
void put_cmap_params(std::vector< int > &node_cmap_ids, std::vector< int > &node_cmap_node_cnts, std::vector< int > &elem_cmap_ids, std::vector< int > &elem_cmap_elem_cnts)
Outputs initial information for communication maps.
std::set< unsigned > border_node_ids
The set which will eventually contain the IDs of "border nodes".
bool active_on_subdomain(subdomain_id_type sid) const
virtual dof_id_type parallel_n_nodes() const =0
std::set< int > nodes_attached_to_local_elems
libMesh numbered node ids attached to local elems.
void get_init_global()
Fills: num_nodes_global, num_elems_global, num_elem_blks_global, num_node_sets_global, num_side_sets_global Call after: read_and_store_header_info() Call before: Any other get_* function from this class.
An object whose state is distributed along a set of processors.
virtual dof_id_type parallel_n_elem() const =0
void compute_num_global_sidesets(const MeshBase &pmesh)
This function uses global communication routines to determine the number of sidesets across the entir...
std::map< dof_id_type, dof_id_type > libmesh_elem_num_to_exodus
void get_eb_info_global()
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
int num_internal_elems
The number of internal FEM elements.
void compute_internal_and_border_elems_and_internal_nodes(const MeshBase &pmesh)
This function constructs the set of border and internal element IDs and internal node IDs present on ...
unsigned _write_as_dimension
void compute_node_maps()
Compute the node maps (really just pack vectors) which map the nodes to internal, border...
void put_elem_cmap(std::vector< std::vector< int >> &elem_cmap_elem_ids, std::vector< std::vector< int >> &elem_cmap_side_ids, std::vector< std::vector< int >> &elem_cmap_proc_ids)
Writes information about elemental communication map.
std::vector< int > num_node_df_per_set
std::map< subdomain_id_type, unsigned > local_subdomain_counts
This map keeps track of the number of elements in each subdomain (block) for this processor...
std::map< int, std::vector< int > > block_id_to_elem_connectivity
This is the block connectivity, i.e.
char ** get_char_star_star()
Provide access to the underlying C data table.
virtual void write_nodesets(const MeshBase &mesh) override
Writes the nodesets for this processor.
std::map< unsigned, std::set< unsigned > >::iterator proc_nodes_touched_iterator
Typedef for an iterator into the data structure above.
void get_ns_param_global()
const FEType & variable_type(const unsigned int i) const
void put_node_map(std::vector< int > &node_mapi, std::vector< int > &node_mapb, std::vector< int > &node_mape)
Outputs IDs of internal, border, and external nodes.
std::vector< int > elem_cmap_elem_cnts
int num_elem_cmaps
The number of elemental communication maps for this processor.
std::vector< int > elem_cmap_ids
const MeshBase & get_mesh() const
virtual const Elem & elem_ref(const dof_id_type i) const
void put_ss_param_global(std::vector< int > &global_sideset_ids, std::vector< int > &num_global_side_counts, std::vector< int > &num_global_side_df_counts)
This function writes information about global side sets.
virtual void write_sidesets(const MeshBase &mesh) override
Writes the sidesets for this processor.
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...
int num_proc_in_file
The number of processors for which the NEMESIS I file stores information.
std::vector< int > node_cmap_node_cnts
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
std::map< unsigned, std::set< unsigned > > proc_nodes_touched_intersections
Another map to store sets of intersections with each other processor (other than ourself, of course).
std::vector< int > exodus_node_num_to_libmesh
void write_exodus_initialization_info(const MeshBase &pmesh, const std::string &title)
This function writes exodus-specific initialization information.
std::vector< int > num_nodes_per_set
void put_init_info(unsigned num_proc, unsigned num_proc_in_file, const char *ftype)
Writing functions.
void put_node_cmap(std::vector< std::vector< int >> &node_cmap_node_ids, std::vector< std::vector< int >> &node_cmap_proc_ids)
Outputs all of the nodal communication maps for this processor.
std::vector< int > elem_mapb
Vector which stores border element IDs.
std::vector< int > node_mapb
Vector which stores border node IDs.
virtual const Node * node_ptr(const dof_id_type i) const =0
std::vector< std::vector< int > > node_cmap_node_ids
2 vectors of vectors for storing the node communication IDs for this processor.
processor_id_type processor_id() const
std::map< unsigned, std::set< std::pair< unsigned, unsigned > > >::iterator proc_border_elem_sets_iterator
Typedef for an iterator into the data structure above.
This class is useful for managing anything that requires a char ** input/output in ExodusII file...
static void nodal_soln(const unsigned int dim, const FEType &fe_t, const Elem *elem, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln, const bool add_p_level=true, const unsigned int vdim=1)
Build the nodal soln from the element soln.
const DofMap & get_dof_map() const
processor_id_type processor_id() const
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
dof_id_type node_id(const unsigned int i) const
std::vector< int > global_elem_blk_cnts
void put_loadbal_param(unsigned num_internal_nodes, unsigned num_border_nodes, unsigned num_external_nodes, unsigned num_internal_elems, unsigned num_border_elems, unsigned num_node_cmaps, unsigned num_elem_cmaps)
Writes load balance parameters, some of which are described below: .) num_internal_nodes - nodes "who...
std::vector< int > elem_mapi
Vector which stores internal element IDs.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
std::map< unsigned, std::set< std::pair< unsigned, unsigned > > > proc_border_elem_sets
Map between processor ID and (element,side) pairs bordering that processor ID.
int num_border_nodes
The number of FEM nodes local to a processor but residing in an element which also has FEM nodes on o...
int num_internal_nodes
To be used with the Nemesis::ne_get_loadbal_param() routine.
std::set< unsigned > internal_elem_ids
A set of internal elem IDs for this processor.
virtual void read_var_names_impl(const char *var_type, int &count, std::vector< std::string > &result) override
read_var_names() dispatches to this function.
int num_border_elems
The number of border FEM elements.
void write_nodal_solution(const NumericVector< Number > ¶llel_soln, const std::vector< std::string > &names, int timestep, const std::vector< std::string > &output_names)
Takes a parallel solution vector containing the node-major solution vector for all variables and outp...
void set_union(T &data, const unsigned int root_id) const
virtual void localize(std::vector< T > &v_local) const =0
Creates a copy of the global vector in the local vector v_local.