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> 62 # include "ne_nemesisI.h" 66 #include <libmesh/restore_warnings.h> 78 bool verbose_in,
bool single_precision) :
83 num_elem_blks_global(0),
84 num_node_sets_global(0),
85 num_side_sets_global(0),
89 num_internal_nodes(0),
91 num_external_nodes(0),
92 num_internal_elems(0),
96 write_complex_abs(true)
99 libmesh_experimental();
111 EX_EXCEPTIONLESS_CHECK_ERR(
ex_err,
"Error flushing buffers to file.");
129 EX_CHECK_ERR(
ex_err,
"Error retrieving nodeset parameters.");
130 message(
"Parameters retrieved successfully for nodeset: ",
id);
144 EX_CHECK_ERR(
ex_err,
"Error retrieving nodeset data.");
145 message(
"Data retrieved successfully for nodeset: ",
id);
154 Nemesis::ne_get_init_global(
ex_id,
186 Nemesis::ne_get_ss_param_global(
ex_id,
194 libMesh::out <<
"[" << this->
processor_id() <<
"] " <<
"Global Sideset IDs, Side Counts, and DF counts:" << std::endl;
219 Nemesis::ne_get_ns_param_global(
ex_id,
227 libMesh::out <<
"[" << this->
processor_id() <<
"] " <<
"Global Nodeset IDs, Node Counts, and DF counts:" << std::endl;
250 Nemesis::ne_get_eb_info_global(
ex_id,
274 Nemesis::ne_get_init_info(
ex_id,
293 Nemesis::ne_get_loadbal_param(
ex_id,
326 Nemesis::ne_get_elem_map(
ex_id,
358 Nemesis::ne_get_node_map(
ex_id,
396 Nemesis::ne_get_cmap_params(
ex_id,
446 Nemesis::ne_get_node_cmap(
ex_id,
451 EX_CHECK_ERR(
nemesis_err_flag,
"Error reading node cmap node and processor ids!");
488 Nemesis::ne_get_elem_cmap(
ex_id,
494 EX_CHECK_ERR(
nemesis_err_flag,
"Error reading elem cmap elem, side, and processor ids!");
525 unsigned num_proc_in_file_in,
526 const char * ftype_in)
529 Nemesis::ne_put_init_info(
ex_id,
532 const_cast<char *>(ftype_in));
542 unsigned num_elem_blks_global_in,
543 unsigned num_node_sets_global_in,
544 unsigned num_side_sets_global_in)
547 Nemesis::ne_put_init_global(
ex_id,
550 num_elem_blks_global_in,
551 num_node_sets_global_in,
552 num_side_sets_global_in);
560 std::vector<int> & global_elem_blk_cnts_in)
563 Nemesis::ne_put_eb_info_global(
ex_id,
564 global_elem_blk_ids_in.data(),
565 global_elem_blk_cnts_in.data());
567 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing global element block information!");
574 std::vector<int> & num_global_node_counts_in,
575 std::vector<int> & num_global_node_df_counts_in)
581 Nemesis::ne_put_ns_param_global(
ex_id,
582 global_nodeset_ids_in.data(),
583 num_global_node_counts_in.data(),
584 num_global_node_df_counts_in.data());
594 std::vector<int> & num_global_side_counts_in,
595 std::vector<int> & num_global_side_df_counts_in)
601 Nemesis::ne_put_ss_param_global(
ex_id,
602 global_sideset_ids_in.data(),
603 num_global_side_counts_in.data(),
604 num_global_side_df_counts_in.data());
614 unsigned num_border_nodes_in,
615 unsigned num_external_nodes_in,
616 unsigned num_internal_elems_in,
617 unsigned num_border_elems_in,
618 unsigned num_node_cmaps_in,
619 unsigned num_elem_cmaps_in)
622 Nemesis::ne_put_loadbal_param(
ex_id,
623 num_internal_nodes_in,
625 num_external_nodes_in,
626 num_internal_elems_in,
640 std::vector<int> & node_cmap_node_cnts_in,
641 std::vector<int> & elem_cmap_ids_in,
642 std::vector<int> & elem_cmap_elem_cnts_in)
645 Nemesis::ne_put_cmap_params(
ex_id,
646 node_cmap_ids_in.empty() ? nullptr : node_cmap_ids_in.data(),
647 node_cmap_node_cnts_in.empty() ? nullptr : node_cmap_node_cnts_in.data(),
648 elem_cmap_ids_in.empty() ? nullptr : elem_cmap_ids_in.data(),
649 elem_cmap_elem_cnts_in.empty() ? nullptr : elem_cmap_elem_cnts_in.data(),
659 std::vector<std::vector<int>> & node_cmap_proc_ids_in)
669 for (
const auto & node_id : node_cmap_node_ids_in[i])
677 for (
const auto & proc_id : node_cmap_proc_ids_in[i])
685 int * node_ids_ptr = node_cmap_node_ids_in[i].empty() ?
686 nullptr : node_cmap_node_ids_in[i].data();
687 int * proc_ids_ptr = node_cmap_proc_ids_in[i].empty() ?
688 nullptr : node_cmap_proc_ids_in[i].data();
692 node_ids_ptr, proc_ids_ptr,
695 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing node communication map to file!");
703 std::vector<int> & node_mapb_in,
704 std::vector<int> & node_mape_in)
707 Nemesis::ne_put_node_map(
ex_id,
708 node_mapi_in.empty() ? nullptr : node_mapi_in.data(),
709 node_mapb_in.empty() ? nullptr : node_mapb_in.data(),
710 node_mape_in.empty() ? nullptr : node_mape_in.data(),
713 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing Nemesis internal and border node maps to file!");
720 std::vector<std::vector<int>> & elem_cmap_side_ids_in,
721 std::vector<std::vector<int>> & elem_cmap_proc_ids_in)
726 Nemesis::ne_put_elem_cmap(
ex_id,
728 elem_cmap_elem_ids_in[i].data(),
729 elem_cmap_side_ids_in[i].data(),
730 elem_cmap_proc_ids_in[i].data(),
733 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing elem communication map to file!");
741 std::vector<int> & elem_mapb_in)
744 Nemesis::ne_put_elem_map(
ex_id,
745 elem_mapi_in.empty() ? nullptr : elem_mapi_in.data(),
746 elem_mapb_in.empty() ? nullptr : elem_mapb_in.data(),
749 EX_CHECK_ERR(
nemesis_err_flag,
"Error writing Nemesis internal and border element maps to file!");
920 const std::string & title_in)
923 pmesh.active_local_elements_end()));
945 EX_CHECK_ERR(
ex_err,
"Error initializing new Nemesis file.");
994 for (; it != end; ++it)
997 libmesh_assert_equal_to (static_cast<unsigned>(this->
elem_cmap_ids[cnt]), it->first);
1000 std::set<std::pair<unsigned,unsigned>> & elem_set = it->second;
1007 std::set<std::pair<unsigned,unsigned>>::iterator elem_set_iter = elem_set.begin();
1010 for (std::size_t j=0, eceis=this->
elem_cmap_elem_ids[cnt].size(); j<eceis; ++j, ++elem_set_iter)
1063 libmesh_assert_less_equal
1076 for (; it != end; ++it)
1079 libmesh_assert_equal_to (static_cast<unsigned>(this->
node_cmap_ids[cnt]), it->first);
1082 std::set<unsigned> &
node_set = it->second;
1088 std::set<unsigned>::iterator node_set_iter =
node_set.begin();
1091 for (std::size_t j=0, nceis=this->
node_cmap_node_ids[cnt].size(); j<nceis; ++j, ++node_set_iter)
1119 for (
const auto & proc_id : id_vec)
1145 for (; it != end; ++it)
1180 for (; it != end; ++it)
1212 std::set<unsigned> all_elem_ids;
1217 std::set<unsigned> neighboring_processor_ids;
1219 for (
const auto & elem : pmesh.active_local_element_ptr_range())
1224 all_elem_ids.insert(elem->id());
1227 bool is_border_elem =
false;
1243 for (
auto node : elem->node_index_range())
1247 for (
auto n : elem->side_index_range())
1249 if (elem->neighbor_ptr(n) !=
nullptr)
1251 unsigned neighbor_proc_id = elem->neighbor_ptr(n)->processor_id();
1257 is_border_elem =
true;
1258 neighboring_processor_ids.insert(neighbor_proc_id);
1261 unsigned nemesis_side_id = conv.get_inverse_side_map(n);
1266 <<
" mapped to (1-based) Exodus side " 1286 std::set_difference(all_elem_ids.begin(), all_elem_ids.end(),
1298 for (
const auto &
id : neighboring_processor_ids)
1305 cast_int<int>(neighboring_processor_ids.size());
1309 <<
"Number of neighboring processor IDs=" 1320 << proc_id <<
" communicates " 1321 <<
set.size() <<
" elements." << std::endl;
1348 std::set<boundary_id_type> global_side_boundary_ids
1357 cast_int<int>(global_side_boundary_ids.size());
1362 global_side_boundary_ids.begin(),
1363 global_side_boundary_ids.end());
1375 typedef std::tuple<dof_id_type, unsigned short int, boundary_id_type> Tuple;
1379 std::vector<Tuple>::iterator
1380 it = bc_triples.begin(),
1381 new_end = bc_triples.end();
1383 while (it != new_end)
1391 std::swap (*it, *new_end);
1398 bc_triples.erase(new_end, bc_triples.end());
1408 cast_int<int>(std::count_if(bc_triples.begin(),
1410 [id](
const Tuple & t)->
bool {
return std::get<2>(t) ==
id; }));
1440 std::set<boundary_id_type> local_node_boundary_ids;
1443 std::set<boundary_id_type> global_node_boundary_ids
1448 local_node_boundary_ids = global_node_boundary_ids;
1455 cast_int<int>(global_node_boundary_ids.size());
1460 global_node_boundary_ids.begin(),
1461 global_node_boundary_ids.end());
1471 for (
const auto &
id : local_node_boundary_ids)
1479 typedef std::tuple<dof_id_type, boundary_id_type> Tuple;
1485 << bc_tuples.size() << std::endl;
1487 for (
const auto & t : bc_tuples)
1488 libMesh::out <<
"(" << std::get<0>(t) <<
", " << std::get<1>(t) <<
") ";
1503 std::vector<Tuple>::iterator
1504 it = bc_tuples.begin(),
1505 new_end = bc_tuples.end();
1507 while (it != new_end)
1515 std::swap(*it, *new_end);
1522 bc_tuples.erase(new_end, bc_tuples.end());
1529 cast_int<int>(std::count_if(bc_tuples.begin(),
1531 [id](
const Tuple & t)->
bool {
return std::get<1>(t) ==
id; }));
1552 std::set<subdomain_id_type> global_subdomain_ids;
1555 std::map<subdomain_id_type, unsigned> global_subdomain_counts;
1557 for (
const auto & elem : pmesh.active_local_element_ptr_range())
1568 global_subdomain_ids.insert(cur_subdomain);
1571 global_subdomain_counts[cur_subdomain]++;
1579 std::vector<subdomain_id_type> global_subdomain_ids_vector(global_subdomain_ids.begin(),
1580 global_subdomain_ids.end());
1586 global_subdomain_ids.insert(global_subdomain_ids_vector.begin(),
1587 global_subdomain_ids_vector.end());
1592 cast_int<int>(global_subdomain_ids.size());
1598 for (
const auto & [subdomain_id, cnt] : global_subdomain_counts)
1601 <<
static_cast<unsigned>(subdomain_id)
1602 <<
", Count: " << cnt <<
", ";
1614 for (
const auto &
id : global_subdomain_ids)
1631 global_subdomain_ids.begin(),
1632 global_subdomain_ids.end());
1657 pmesh.active_local_elements_end());
1675 <<
"local_subdomain_counts [" <<
static_cast<unsigned>(sbd_id) <<
"]= " 1685 for (
const auto & elem : pmesh.active_local_element_ptr_range())
1688 for (
auto n : elem->node_index_range())
1739 for (
auto & [block_id, elem_ids_this_subdomain] :
subdomain_map)
1744 libmesh_error_msg_if(elem_ids_this_subdomain.size() == 0,
1745 "Error, no element IDs found in subdomain " << block_id);
1760 current_block_connectivity.clear();
1761 current_block_connectivity.resize(elem_ids_this_subdomain.size() * this->
num_nodes_per_elem);
1763 for (
auto i :
index_range(elem_ids_this_subdomain))
1765 auto elem_id = elem_ids_this_subdomain[i];
1795 for (
auto j :
make_range(this->num_nodes_per_elem))
1798 const unsigned int elem_node_index = conv.get_inverse_node_map(j);
1800 current_block_connectivity[connect_index] =
1802 elem.
node_id(elem_node_index));
1821 std::map<unsigned, std::set<unsigned>> proc_nodes_touched;
1829 for (
const auto & elem : pmesh.active_element_ptr_range())
1833 std::set<unsigned> & set_p = proc_nodes_touched[ elem->processor_id() ];
1836 for (
auto node : elem->node_index_range())
1837 set_p.insert(elem->node_id(node));
1843 <<
"] proc_nodes_touched contains " 1844 << proc_nodes_touched.size()
1845 <<
" sets of nodes." 1848 for (
const auto & [proc_id,
set] : proc_nodes_touched)
1850 <<
"] proc_nodes_touched[" << proc_id <<
"] has " 1860 for (
auto & [proc_id, other_set] : proc_nodes_touched)
1866 std::set<unsigned int> this_intersection;
1869 std::set<unsigned> & my_set = proc_nodes_touched[this->
processor_id()];
1871 std::set_intersection(my_set.begin(), my_set.end(),
1872 other_set.begin(), other_set.end(),
1873 std::inserter(this_intersection, this_intersection.end()));
1875 if (!this_intersection.empty())
1877 (proc_id, std::move(this_intersection));
1884 <<
"] this->proc_nodes_touched_intersections[" << proc_id <<
"] has " 1903 std::set<unsigned> & other_set = pr.second;
1904 std::set<unsigned> intermediate_result;
1907 other_set.begin(), other_set.end(),
1908 std::inserter(intermediate_result, intermediate_result.end()));
1914 libmesh_assert_less_equal
1915 (this->proc_nodes_touched_intersections.size(),
1942 std::map<boundary_id_type, std::vector<int>> local_node_boundary_id_lists;
1949 typedef std::tuple<dof_id_type, boundary_id_type> Tuple;
1950 std::vector<Tuple> bc_tuples =
mesh.get_boundary_info().build_node_list();
1955 << bc_tuples.size() << std::endl;
1957 for (
const auto & t : bc_tuples)
1958 libMesh::out <<
"(" << std::get<0>(t) <<
", " << std::get<1>(t) <<
") ";
1965 for (
const auto & t : bc_tuples)
1974 std::vector<int> & current_id_set = local_node_boundary_id_lists[std::get<1>(t)];
1978 current_id_set.push_back( it->second );
1985 for (
const auto & [bndry_id,
set] : local_node_boundary_id_lists)
1990 for (
const auto &
id :
set)
2004 const std::string & current_ns_name =
2005 mesh.get_boundary_info().get_nodeset_name
2006 (cast_int<boundary_id_type>(nodeset_id));
2010 names_table.push_back_entry(current_ns_name);
2015 <<
"] Writing out Exodus nodeset info for ID: " << nodeset_id
2016 <<
", Name: " << current_ns_name
2021 int exodus_id = nodeset_id;
2031 if (
const auto it = local_node_boundary_id_lists.find (cast_int<boundary_id_type>(nodeset_id));
2032 it == local_node_boundary_id_lists.end())
2037 <<
"] No nodeset data for ID: " << nodeset_id
2038 <<
" on this processor." << std::endl;
2041 this->
ex_err = exII::ex_put_node_set_param(this->
ex_id,
2045 EX_CHECK_ERR(this->
ex_err,
"Error writing nodeset parameters in Nemesis");
2051 const std::vector<int> & current_nodeset_ids = it->second;
2054 this->
ex_err = exII::ex_put_node_set_param(this->
ex_id,
2056 current_nodeset_ids.size(),
2059 EX_CHECK_ERR(this->
ex_err,
"Error writing nodeset parameters in Nemesis");
2064 current_nodeset_ids.data());
2066 EX_CHECK_ERR(this->
ex_err,
"Error writing nodesets in Nemesis");
2074 names_table.get_char_star_star());
2075 EX_CHECK_ERR(
ex_err,
"Error writing nodeset names");
2092 std::map<boundary_id_type, std::vector<int>> local_elem_boundary_id_lists;
2093 std::map<boundary_id_type, std::vector<int>> local_elem_boundary_id_side_lists;
2096 std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> bndry_elem_side_id_list =
2097 mesh.get_boundary_info().build_side_list();
2100 for (
const auto & t : bndry_elem_side_id_list)
2103 const Elem * elem =
mesh.elem_ptr(std::get<0>(t));
2105 std::vector<const Elem *> family;
2106 #ifdef LIBMESH_ENABLE_AMR 2113 family.push_back( elem );
2119 for (
const auto & tree_elem : family)
2122 const Elem & f =
mesh.elem_ref(f_id);
2135 local_elem_boundary_id_side_lists[ std::get<2>(t) ].push_back(conv.get_inverse_side_map( std::get<1>(t) ));
2149 const std::string & current_ss_name =
2150 mesh.get_boundary_info().get_sideset_name
2151 (cast_int<boundary_id_type>(exodus_id));
2155 names_table.push_back_entry(current_ss_name);
2160 <<
"] Writing out Exodus sideset info for ID: " << exodus_id
2161 <<
", Name: " << current_ss_name
2166 if (
const auto it = local_elem_boundary_id_lists.find (cast_int<boundary_id_type>(exodus_id));
2167 it == local_elem_boundary_id_lists.end())
2172 <<
"] No sideset data for ID: " << exodus_id
2173 <<
" on this processor." << std::endl;
2176 this->
ex_err = exII::ex_put_side_set_param(this->
ex_id,
2180 EX_CHECK_ERR(this->
ex_err,
"Error writing sideset parameters in Nemesis");
2186 const std::vector<int> & current_sideset_elem_ids = it->second;
2189 std::vector<int> & current_sideset_side_ids =
2190 libmesh_map_find(local_elem_boundary_id_side_lists,
2191 cast_int<boundary_id_type>(exodus_id));
2194 this->
ex_err = exII::ex_put_side_set_param(this->
ex_id,
2196 current_sideset_elem_ids.size(),
2199 EX_CHECK_ERR(this->
ex_err,
"Error writing sideset parameters in Nemesis");
2204 current_sideset_elem_ids.data(),
2205 current_sideset_side_ids.data());
2207 EX_CHECK_ERR(this->
ex_err,
"Error writing sidesets in Nemesis");
2216 names_table.get_char_star_star());
2217 EX_CHECK_ERR(
ex_err,
"Error writing sideset names");
2228 x.resize(local_num_nodes);
2229 y.resize(local_num_nodes);
2230 z.resize(local_num_nodes);
2241 if (local_num_nodes)
2244 ex_err = exII::ex_put_coord
2249 EX_CHECK_ERR(
ex_err,
"Error writing node coordinates");
2253 EX_CHECK_ERR(
ex_err,
"Error writing node num map");
2257 ex_err = exII::ex_put_coord(
ex_id,
nullptr,
nullptr,
nullptr);
2258 EX_CHECK_ERR(
ex_err,
"Error writing empty node coordinates");
2260 ex_err = exII::ex_put_node_num_map(
ex_id,
nullptr);
2261 EX_CHECK_ERR(
ex_err,
"Error writing empty node num map");
2288 (
mesh.subdomain_name(restrict_int<subdomain_id_type>(this->global_elem_blk_ids[i])));
2295 this->
ex_err = exII::ex_put_elem_block(this->
ex_id,
2302 EX_CHECK_ERR(this->
ex_err,
"Error writing element block from Nemesis.");
2309 cast_int<subdomain_id_type>(it->first);
2310 const std::vector<int> & this_block_connectivity = it->second;
2311 std::vector<dof_id_type> & elements_in_this_block =
subdomain_map[block];
2324 conv.exodus_elem_type().c_str(),
2325 elements_in_this_block.size(),
2328 EX_CHECK_ERR(
ex_err,
"Error writing element block from Nemesis.");
2332 this_block_connectivity.data());
2333 EX_CHECK_ERR(
ex_err,
"Error writing element connectivities from Nemesis.");
2340 EX_CHECK_ERR(
ex_err,
"Error writing element map");
2344 EX_CHECK_ERR(
ex_err,
"Error writing element block names");
2353 const std::vector<std::string> & names,
2356 int num_vars = cast_int<int>(names.size());
2359 for (
int c=0; c<num_vars; c++)
2361 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 2362 std::vector<Real> real_parts(
num_nodes);
2363 std::vector<Real> imag_parts(
num_nodes);
2364 std::vector<Real> magnitudes(
num_nodes);
2369 real_parts[i] =
value.real();
2370 imag_parts[i] =
value.imag();
2371 magnitudes[i] = std::abs(
value);
2377 std::vector<Number> cur_soln(this->num_nodes);
2391 const std::vector<std::string> & names,
2393 const std::vector<std::string> & output_names)
2395 int num_vars = cast_int<int>(names.size());
2397 for (
int c=0; c<num_vars; c++)
2400 auto pos = std::find(output_names.begin(), output_names.end(), names[c]);
2403 if (pos == output_names.end())
2409 int variable_name_position =
2413 std::vector<numeric_index_type> required_indices(this->
num_nodes);
2420 std::vector<Number> local_soln;
2421 parallel_soln.
localize(local_soln, required_indices);
2423 #ifndef LIBMESH_USE_COMPLEX_NUMBERS 2429 std::vector<Real> real_parts(
num_nodes);
2430 std::vector<Real> imag_parts(
num_nodes);
2431 std::vector<Real> magnitudes(
num_nodes);
2435 real_parts[i] = local_soln[i].real();
2436 imag_parts[i] = local_soln[i].imag();
2437 magnitudes[i] = std::abs(local_soln[i]);
2451 const std::vector<std::pair<unsigned int, unsigned int>> & var_nums,
2453 const std::vector<std::string> & output_names)
2460 for (
auto [sys_num, var] : var_nums)
2465 auto pos = std::find(output_names.begin(), output_names.end(),
name);
2468 if (pos == output_names.end())
2474 int variable_name_position =
2478 std::vector<numeric_index_type> required_indices(this->
num_nodes);
2482 std::vector<Number> local_soln;
2487 std::vector<numeric_index_type> scalar_indices;
2490 required_indices[i] = scalar_indices[0];
2497 bool found_all_indices =
true;
2501 if (node.
n_comp(sys_num, var))
2502 required_indices[i] = node.
dof_number(sys_num, var, 0);
2505 found_all_indices =
false;
2510 if (found_all_indices)
2513 if (!found_all_indices)
2521 std::vector<Number> elem_soln;
2522 std::vector<Number> nodal_soln;
2523 std::vector<dof_id_type> dof_indices;
2525 for (
const auto & elem :
mesh.active_local_element_ptr_range())
2529 elem_soln.resize(dof_indices.size());
2532 elem_soln[i] = sys_soln(dof_indices[i]);
2541 if (!elem->infinite())
2542 for (
auto n : elem->node_index_range())
2544 const std::size_t exodus_num =
2546 libmesh_assert_greater(exodus_num, 0);
2547 libmesh_assert_less(exodus_num-1, local_soln.size());
2548 local_soln[exodus_num-1] = nodal_soln[n];
2554 #ifndef LIBMESH_USE_COMPLEX_NUMBERS 2560 std::vector<Real> real_parts(
num_nodes);
2561 std::vector<Real> imag_parts(
num_nodes);
2562 std::vector<Real> magnitudes(
num_nodes);
2566 real_parts[i] = local_soln[i].real();
2567 imag_parts[i] = local_soln[i].imag();
2568 magnitudes[i] = std::abs(local_soln[i]);
2583 const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
2586 if (names.size() == 0)
2612 if (vars_active_subdomains[var].empty() ||
2614 truth_tab[names.size() * blk + var] = 1;
2617 if (truth_tab.size())
2621 cast_int<int>(names.size()),
2623 EX_CHECK_ERR(
ex_err,
"Error writing element truth table.");
2632 const std::vector<std::pair<unsigned int, unsigned int>> &var_nums,
2634 const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
2644 unsigned int var_ctr = 0;
2647 const unsigned int sys_num = var_nums[v].first;
2648 const unsigned int var = var_nums[v].second;
2655 const unsigned int n_comps =
2659 const auto & active_subdomains = vars_active_subdomains[v];
2664 restrict_int<subdomain_id_type>(sbd_id_int);
2666 const std::vector<dof_id_type> empty_vec;
2667 const std::vector<dof_id_type> & elem_ids =
2673 if ((active_subdomains.empty() || active_subdomains.count(sbd_id)) && elem_ids.size())
2675 std::vector<numeric_index_type> required_indices;
2676 required_indices.reserve(elem_ids.size());
2682 libmesh_assert_equal_to(n_comps,
mesh.elem_ref(elem_ids.back()).n_comp(sys_num, var));
2686 for (
unsigned int comp = 0; comp < n_comps; ++comp)
2688 for (
const auto &
id : elem_ids)
2689 required_indices.push_back(
mesh.elem_ref(
id).dof_number(sys_num, var, comp));
2691 std::vector<Number> local_soln;
2695 required_indices.clear();
2702 if (local_soln.size())
2704 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 2706 std::vector<Real> local_soln_buffer(local_soln.size());
2707 std::transform(local_soln.begin(), local_soln.end(),
2708 local_soln_buffer.begin(), [](
Number n) {
return n.real(); });
2711 static_cast<int>(stride*(var_ctr+comp)+1),
2712 static_cast<int>(sbd_id),
2713 static_cast<int>(local_soln.size()),
2715 EX_CHECK_ERR(
ex_err,
"Error writing element real values.");
2717 std::transform(local_soln.begin(), local_soln.end(),
2718 local_soln_buffer.begin(), [](
Number n) {
return n.imag(); });
2721 static_cast<int>(stride*(var_ctr+comp)+2),
2722 static_cast<int>(sbd_id),
2723 static_cast<int>(local_soln.size()),
2725 EX_CHECK_ERR(
ex_err,
"Error writing element imaginary values.");
2729 std::transform(local_soln.begin(), local_soln.end(),
2730 local_soln_buffer.begin(), [](
Number n) {
return std::abs(n); });
2733 static_cast<int>(stride*(var_ctr+comp)+2),
2734 static_cast<int>(sbd_id),
2735 static_cast<int>(local_soln.size()),
2737 EX_CHECK_ERR(
ex_err,
"Error writing element magnitudes.");
2739 #else // LIBMESH_USE_COMPLEX_NUMBERS 2742 static_cast<int>(var_ctr+comp+1),
2743 static_cast<int>(sbd_id),
2744 static_cast<int>(local_soln.size()),
2746 EX_CHECK_ERR(
ex_err,
"Error writing element values.");
2747 #endif // LIBMESH_USE_COMPLEX_NUMBERS 2763 std::vector<std::string> & result)
2774 const std::size_t n_names = result.size();
2779 (n_names ?
nullptr : &n_names));
2781 this->
comm().
min(pid_broadcasting_names);
2793 std::ostringstream file_oss;
2812 unsigned int field_width = cast_int<unsigned int>(file_oss.str().size());
2815 libMesh::out <<
"field_width=" << field_width << std::endl;
2818 file_oss << base_filename
2820 <<
'.' << std::setfill(
'0') << std::setw(field_width) << this->
processor_id();
2823 return file_oss.str();
2828 #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
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
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.
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
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 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
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.
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< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
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.