20 #include "libmesh/distributed_mesh.h" 21 #include "libmesh/dof_map.h" 22 #include "libmesh/elem.h" 23 #include "libmesh/exodusII_io.h" 24 #include "libmesh/libmesh_logging.h" 25 #include "libmesh/nemesis_io.h" 26 #include "libmesh/nemesis_io_helper.h" 27 #include "libmesh/node.h" 28 #include "libmesh/parallel.h" 29 #include "libmesh/utility.h" 30 #include "libmesh/boundary_info.h" 31 #include "libmesh/mesh_communication.h" 32 #include "libmesh/fe_type.h" 33 #include "libmesh/equation_systems.h" 34 #include "libmesh/numeric_vector.h" 35 #include "libmesh/int_range.h" 49 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 50 struct CompareGlobalIdxMappings
54 bool operator()(
const std::pair<unsigned int, unsigned int> & a,
55 const std::pair<unsigned int, unsigned int> & b)
const 56 {
return a.first < b.first; }
60 bool operator()(
const std::pair<unsigned int, unsigned int> & a,
61 const unsigned int b)
const 62 {
return a.first < b; }
64 #endif // defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 71 inline unsigned int to_uint (
const T & t )
73 libmesh_assert_equal_to (t, static_cast<T>(static_cast<unsigned int>(t)));
75 return static_cast<unsigned int>(t);
80 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) && !defined(NDEBUG) 81 inline bool global_idx_mapping_equality (
const std::pair<unsigned int, unsigned int> & a,
82 const std::pair<unsigned int, unsigned int> & b)
84 return a.first == b.first;
95 bool single_precision) :
99 #
if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
105 _allow_empty_variables(false)
114 bool single_precision) :
118 #
if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
124 _allow_empty_variables(false)
142 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 153 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 180 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 186 std::vector<unsigned char> pid_send_partner (this->
n_processors(), 0);
192 for (
unsigned int cmap=0; cmap<to_uint(
nemhelper->num_node_cmaps); cmap++)
194 libmesh_assert_less (
nemhelper->node_cmap_ids[cmap], this->n_processors());
196 pid_send_partner[
nemhelper->node_cmap_ids[cmap]] = 1;
201 const std::vector<unsigned char> pid_recv_partner (pid_send_partner);
213 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 216 LOG_SCOPE (
"read()",
"Nemesis_IO");
219 parallel_object_only();
229 std::string nemesis_filename =
nemhelper->construct_nemesis_filename(base_filename);
232 libMesh::out <<
"Opening file: " << nemesis_filename << std::endl;
235 nemhelper->open(nemesis_filename.c_str(),
true);
265 libmesh_error_msg_if(
nemhelper->num_external_nodes,
266 "ERROR: there should be no external nodes in an element-based partitioning!");
268 libmesh_assert_equal_to (
nemhelper->num_nodes,
272 libmesh_assert_equal_to (
nemhelper->num_elem,
306 libmesh_assert_equal_to (to_uint(
nemhelper->num_node_cmaps),
nemhelper->node_cmap_node_cnts.size());
307 libmesh_assert_equal_to (to_uint(
nemhelper->num_node_cmaps),
nemhelper->node_cmap_node_ids.size());
308 libmesh_assert_equal_to (to_uint(
nemhelper->num_node_cmaps),
nemhelper->node_cmap_proc_ids.size());
316 std::vector<processor_id_type> node_ownership (
nemhelper->num_internal_nodes +
318 this->processor_id());
321 std::map<unsigned int, unsigned int> pid_to_cmap_map;
324 for (
unsigned int cmap=0; cmap<to_uint(
nemhelper->num_node_cmaps); cmap++)
327 libmesh_assert_equal_to (to_uint(
nemhelper->node_cmap_node_cnts[cmap]),
328 nemhelper->node_cmap_node_ids[cmap].size());
330 libmesh_assert_equal_to (to_uint(
nemhelper->node_cmap_node_cnts[cmap]),
331 nemhelper->node_cmap_proc_ids[cmap].size());
336 cast_int<processor_id_type>(
nemhelper->node_cmap_ids[cmap]);
338 libmesh_assert_less (adjcnt_pid_idx, this->
n_processors());
339 libmesh_assert_not_equal_to (adjcnt_pid_idx, this->
processor_id());
344 pid_to_cmap_map[adjcnt_pid_idx] = cmap;
350 libmesh_assert_equal_to
352 cast_int<processor_id_type>(
nemhelper->node_cmap_proc_ids[cmap][
idx]));
355 const unsigned int local_node_idx =
nemhelper->node_cmap_node_ids[cmap][
idx]-1;
357 libmesh_assert_less (local_node_idx, node_ownership.size());
361 node_ownership[local_node_idx] =
362 std::min(node_ownership[local_node_idx], adjcnt_pid_idx);
368 unsigned int num_nodes_i_must_number = 0;
370 for (
const auto & pid : node_ownership)
372 num_nodes_i_must_number++;
375 libmesh_assert_greater_equal (num_nodes_i_must_number,
nemhelper->num_internal_nodes);
380 <<
"num_nodes_i_must_number=" 381 << num_nodes_i_must_number
388 std::vector<int> all_loadbal_data ( 8 );
389 all_loadbal_data[0] =
nemhelper->num_internal_nodes;
390 all_loadbal_data[1] =
nemhelper->num_border_nodes;
391 all_loadbal_data[2] =
nemhelper->num_external_nodes;
392 all_loadbal_data[3] =
nemhelper->num_internal_elems;
393 all_loadbal_data[4] =
nemhelper->num_border_elems;
394 all_loadbal_data[5] =
nemhelper->num_node_cmaps;
395 all_loadbal_data[6] =
nemhelper->num_elem_cmaps;
396 all_loadbal_data[7] = num_nodes_i_must_number;
406 std::vector<std::vector<int>>
407 needed_node_idxs (
nemhelper->num_node_cmaps);
409 std::vector<Parallel::Request>
410 needed_nodes_requests (
nemhelper->num_node_cmaps);
412 for (
unsigned int cmap=0; cmap<to_uint(
nemhelper->num_node_cmaps); cmap++)
418 needed_node_idxs[cmap].reserve (
nemhelper->node_cmap_node_cnts[cmap]);
420 const unsigned int adjcnt_pid_idx =
nemhelper->node_cmap_ids[cmap];
426 local_node_idx =
nemhelper->node_cmap_node_ids[cmap][
idx]-1,
427 owning_pid_idx = node_ownership[local_node_idx];
430 if (owning_pid_idx == adjcnt_pid_idx)
433 global_node_idx =
nemhelper->node_num_map[local_node_idx]-1;
434 needed_node_idxs[cmap].push_back(global_node_idx);
439 needed_node_idxs[cmap],
440 needed_nodes_requests[cmap],
448 std::vector<unsigned int>
452 all_num_nodes_i_must_number[pid] = all_loadbal_data[8*pid + 7];
455 libmesh_assert (std::accumulate(all_num_nodes_i_must_number.begin(),
456 all_num_nodes_i_must_number.end(),
459 unsigned int my_next_node = 0;
461 my_next_node += all_num_nodes_i_must_number[pid];
463 const unsigned int my_node_offset = my_next_node;
473 for (
unsigned int i=0; i<to_uint(
nemhelper->num_internal_nodes); ++i)
475 const unsigned int local_node_idx =
nemhelper->node_mapi[i]-1;
477 const unsigned int owning_pid_idx = node_ownership[local_node_idx];
481 libmesh_assert_equal_to (owning_pid_idx, this->
processor_id());
482 libmesh_assert_less (my_next_node,
nemhelper->num_nodes_global);
491 this->processor_id());
494 if (added_node->
id() != my_next_node)
497 <<
", but we wanted ID " << my_next_node << std::endl;
503 #ifdef LIBMESH_ENABLE_UNIQUE_ID 508 nemhelper->node_num_map[local_node_idx] = my_next_node++ + 1;
516 typedef std::vector<std::pair<unsigned int, unsigned int>> global_idx_mapping_type;
517 global_idx_mapping_type old_global_to_new_global_map;
518 old_global_to_new_global_map.reserve (num_nodes_i_must_number
521 CompareGlobalIdxMappings global_idx_mapping_comp;
523 for (
unsigned int i=0; i<to_uint(
nemhelper->num_border_nodes); ++i)
526 local_node_idx =
nemhelper->node_mapb[i]-1,
527 owning_pid_idx = node_ownership[local_node_idx];
533 global_node_idx =
nemhelper->node_num_map[local_node_idx]-1;
537 old_global_to_new_global_map.emplace_back(global_node_idx, my_next_node);
546 this->processor_id());
549 if (added_node->
id() != my_next_node)
552 <<
", but we wanted ID " << my_next_node << std::endl;
558 #ifdef LIBMESH_ENABLE_UNIQUE_ID 563 nemhelper->node_num_map[local_node_idx] = my_next_node++ + 1;
567 libmesh_assert_equal_to (num_nodes_i_must_number, (my_next_node - my_node_offset));
570 std::sort (old_global_to_new_global_map.begin(),
571 old_global_to_new_global_map.end(),
572 global_idx_mapping_comp);
575 libmesh_assert (std::unique (old_global_to_new_global_map.begin(),
576 old_global_to_new_global_map.end(),
577 global_idx_mapping_equality) ==
578 old_global_to_new_global_map.end());
582 std::map<unsigned int, std::vector<int>> requested_node_idxs;
584 std::vector<Parallel::Request> requested_nodes_requests(
nemhelper->num_node_cmaps);
593 std::vector<bool> processed_cmap (
nemhelper->num_node_cmaps,
false);
595 for (
unsigned int comm_step=0; comm_step<2*to_uint(
nemhelper->num_node_cmaps); comm_step++)
599 status (this->
comm().probe (Parallel::any_source,
602 requesting_pid_idx =
status.source(),
603 source_pid_idx =
status.source();
609 const unsigned int cmap = pid_to_cmap_map[source_pid_idx];
611 if (!processed_cmap[cmap])
613 processed_cmap[cmap] =
true;
620 std::vector<int> & xfer_buf (requested_node_idxs[requesting_pid_idx]);
623 this->
comm().
receive (requesting_pid_idx, xfer_buf, nodes_tag);
629 const unsigned int old_global_node_idx = xfer_buf[i];
634 const global_idx_mapping_type::const_iterator it =
635 std::lower_bound (old_global_to_new_global_map.begin(),
636 old_global_to_new_global_map.end(),
638 global_idx_mapping_comp);
641 libmesh_assert_equal_to (it->first, old_global_node_idx);
642 libmesh_assert_greater_equal (it->second, my_node_offset);
643 libmesh_assert_less (it->second, my_next_node);
646 xfer_buf[i] = it->second;
650 this->
comm().
send (requesting_pid_idx,
652 requested_nodes_requests[cmap],
668 libmesh_assert_equal_to (to_uint(
nemhelper->node_cmap_ids[cmap]), source_pid_idx);
672 needed_node_idxs[cmap],
675 libmesh_assert_less_equal (needed_node_idxs[cmap].size(),
676 nemhelper->node_cmap_node_ids[cmap].size());
678 for (std::size_t i=0, j=0, ncnis=
nemhelper->node_cmap_node_ids[cmap].size(); i < ncnis; i++)
681 local_node_idx =
nemhelper->node_cmap_node_ids[cmap][i]-1,
682 owning_pid_idx = node_ownership[local_node_idx];
686 if (owning_pid_idx == source_pid_idx)
688 libmesh_assert_less (j, needed_node_idxs[cmap].size());
691 global_node_idx = needed_node_idxs[cmap][j++];
699 cast_int<dof_id_type>(global_node_idx),
700 cast_int<processor_id_type>(source_pid_idx));
703 if (added_node->
id() != global_node_idx)
706 <<
", but we wanted ID " << global_node_idx << std::endl;
712 #ifdef LIBMESH_ENABLE_UNIQUE_ID 717 nemhelper->node_num_map[local_node_idx] = global_node_idx + 1;
729 libmesh_assert_equal_to ((my_next_node - my_node_offset), to_uint(
nemhelper->num_nodes));
749 Parallel::wait (needed_nodes_requests);
750 Parallel::wait (requested_nodes_requests);
751 requested_node_idxs.clear();
779 int sum_internal_elems=0, sum_border_elems=0;
780 for (
unsigned int j=3,c=0; c<this->
n_processors(); j+=8,++c)
781 sum_internal_elems += all_loadbal_data[j];
783 for (
unsigned int j=4,c=0; c<this->
n_processors(); j+=8,++c)
784 sum_border_elems += all_loadbal_data[j];
789 libMesh::out <<
"sum_internal_elems=" << sum_internal_elems << std::endl;
792 libMesh::out <<
"sum_border_elems=" << sum_border_elems << std::endl;
795 libmesh_assert_equal_to (sum_internal_elems+sum_border_elems,
nemhelper->num_elems_global);
840 std::size_t local_elem_num = 0;
844 for (
unsigned int i=0; i<to_uint(
nemhelper->num_elem_blk); i++)
856 if (!
nemhelper->num_elem_this_blk)
continue;
860 cast_int<subdomain_id_type>(
nemhelper->block_ids[i]);
863 const std::string type_str (
nemhelper->elem_type.data() );
866 const auto & conv =
nemhelper->get_conversion(type_str);
869 libMesh::out <<
"Reading a block of " << type_str <<
" elements." << std::endl;
872 for (
unsigned int j=0; j<to_uint(
nemhelper->num_elem_this_blk); j++)
874 auto uelem =
Elem::build (conv.libmesh_elem_type());
880 uelem->subdomain_id() = subdomain_id;
882 uelem->set_id() =
nemhelper->elem_num_map[local_elem_num++]-1;
887 #ifdef LIBMESH_ENABLE_UNIQUE_ID 888 uelem->set_unique_id(uelem->id());
902 libmesh_assert_equal_to(elem->
id(),
903 cast_int<dof_id_type>(
nemhelper->elem_num_map[local_elem_num-1]-1));
908 <<
"Setting nodes for Elem " << elem->
id() << std::endl;
910 for (
unsigned int k=0; k<to_uint(
nemhelper->num_nodes_per_elem); k++)
914 conv.get_node_map(k)),
915 local_node_idx =
nemhelper->connect[gi]-1,
916 global_node_idx =
nemhelper->node_num_map[local_node_idx]-1;
937 unsigned char max_dim_seen = 0;
940 max_dim_seen =
static_cast<unsigned char>(i);
945 this->
comm().
max(max_dim_seen);
951 <<
"max_dim_seen=" << +max_dim_seen << std::endl;
959 "Cannot open dimension " 961 <<
" mesh file when configured without " 973 <<
"Read global sideset parameter information." << std::endl;
977 <<
"Number of global sideset IDs: " <<
nemhelper->global_sideset_ids.size() << std::endl;
994 <<
"nemhelper->num_side_sets = " <<
nemhelper->num_side_sets << std::endl;
997 <<
"nemhelper->num_elem_all_sidesets = " <<
nemhelper->num_elem_all_sidesets << std::endl;
1014 int sum_num_global_side_counts = std::accumulate(
nemhelper->num_global_side_counts.begin(),
1015 nemhelper->num_global_side_counts.end(),
1019 int sum_num_elem_all_sidesets =
nemhelper->num_elem_all_sidesets;
1020 this->
comm().
sum(sum_num_elem_all_sidesets);
1022 libmesh_error_msg_if(sum_num_global_side_counts != sum_num_elem_all_sidesets,
1023 "Error! global side count reported by Nemesis does not " 1024 "match the side count reported by the individual files!");
1031 for (
int offset=0, i=0; i<
nemhelper->num_side_sets; i++)
1033 offset += (i > 0 ?
nemhelper->num_sides_per_set[i-1] : 0);
1065 const std::size_t local_id =
nemhelper->elem_list[e]-1;
1073 const auto & conv =
nemhelper->get_conversion(elem->
type());
1079 cast_int<unsigned short>(conv.get_side_map(
nemhelper->side_list[e]-1)),
1080 cast_int<boundary_id_type>(
nemhelper->id_list[e]));
1094 libmesh_error_msg_if(nbcs !=
nemhelper->elem_list.size(),
1096 <<
"BoundaryInfo contains " 1098 <<
" boundary conditions, while the Exodus file had " 1131 for (
int nodeset=0; nodeset<
nemhelper->num_node_sets; nodeset++)
1134 int nodeset_id =
nemhelper->nodeset_ids[nodeset];
1139 libMesh::out <<
"nemhelper->nodeset_ids[" << nodeset <<
"]=" << nodeset_id << std::endl;
1149 libmesh_error_msg_if(to_uint(
nemhelper->node_list[node]-1) >=
nemhelper->node_num_map.size(),
1150 "Error, index is past the end of node_num_map array!");
1159 <<
"nodeset " << nodeset
1160 <<
", local node number: " <<
nemhelper->node_list[node]-1
1161 <<
", global node id: " << global_node_id
1167 (cast_int<dof_id_type>(global_node_id),
1168 cast_int<boundary_id_type>(nodeset_id));
1206 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1217 libmesh_error_msg(
"ERROR, Nemesis API is not defined!");
1220 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1226 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1234 std::string nemesis_filename =
nemhelper->construct_nemesis_filename(base_filename);
1241 libmesh_warning(
"Warning: Appending in Nemesis_IO::write() does not make sense.\n" 1242 "Creating a new file instead!");
1256 nemhelper->write_nodal_coordinates(mesh);
1274 libmesh_warning(
"Warning: Mesh contains edge boundary IDs, but these " 1275 "are not supported by the Nemesis format.");
1282 libmesh_error_msg(
"ERROR, Nemesis API is not defined!");
1285 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1288 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1298 nemhelper->write_timestep(timestep, time);
1308 libmesh_error_msg(
"ERROR, Nemesis API is not defined!");
1311 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1315 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1318 const std::vector<std::string> & names)
1322 std::string nemesis_filename =
nemhelper->construct_nemesis_filename(fname);
1331 nemhelper->open(nemesis_filename.c_str(),
false);
1336 nemhelper->read_and_store_header_info();
1354 nemhelper->write_nodal_coordinates(mesh);
1360 libmesh_warning(
"Warning: Mesh contains edge boundary IDs, but these " 1361 "are not supported by the ExodusII format.");
1369 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 1370 std::vector<std::string> complex_names =
1372 nemhelper->initialize_nodal_variables(complex_names);
1374 nemhelper->initialize_nodal_variables(names);
1381 const std::vector<std::string> &)
1383 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1390 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1394 const std::vector<std::string> & names)
1396 LOG_SCOPE(
"write_nodal_data(parallel)",
"Nemesis_IO");
1401 std::vector<std::string> output_names;
1406 output_names = names;
1419 const std::set<std::string> * system_names)
1421 LOG_SCOPE(
"write_nodal_data(parallel)",
"Nemesis_IO");
1426 std::vector<std::string> output_names;
1435 std::vector<std::pair<unsigned int, unsigned int>> var_nums;
1438 if (!output_names.empty())
1448 const std::vector<std::string> &)
1450 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1454 const EquationSystems &,
1455 const std::set<std::string> *)
1457 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1464 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1468 libmesh_error_msg_if(!
nemhelper->opened_for_writing,
1469 "ERROR, Nemesis file must be initialized before outputting elemental variables.");
1472 std::vector<std::string> names;
1481 std::vector<std::string> monomials;
1489 for (
const auto & var : monomials)
1491 names.push_back(var);
1496 std::vector<std::pair<unsigned int, unsigned int>> var_nums =
1501 if (var_nums.empty())
1504 libMesh::out <<
"No CONSTANT, MONOMIAL or CONSTANT, MONOMIAL_VEC data to be written." << std::endl;
1511 std::vector<std::set<subdomain_id_type>> vars_active_subdomains;
1516 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 1517 std::vector<std::string> complex_names =
1520 std::vector<std::set<subdomain_id_type>>
1521 complex_vars_active_subdomains =
1522 nemhelper->get_complex_vars_active_subdomains(vars_active_subdomains,
1524 nemhelper->initialize_element_variables(complex_names, complex_vars_active_subdomains);
1534 complex_vars_active_subdomains);
1544 nemhelper->initialize_element_variables(names, vars_active_subdomains);
1554 vars_active_subdomains);
1562 libmesh_not_implemented();
1569 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1572 const std::vector<Number> & soln,
1573 const std::vector<std::string> & names)
1575 LOG_SCOPE(
"write_nodal_data(serialized)",
"Nemesis_IO");
1585 const std::vector<Number> &,
1586 const std::vector<std::string> &)
1588 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1596 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1599 const std::vector<std::string> & names)
1601 libmesh_error_msg_if(!
nemhelper->opened_for_writing,
1602 "ERROR, Nemesis file must be initialized before outputting global variables.");
1604 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 1606 std::vector<std::string> complex_names =
1609 nemhelper->initialize_global_variables(complex_names);
1611 unsigned int num_values = soln.size();
1612 unsigned int num_vars = names.size();
1613 unsigned int num_elems = num_values / num_vars;
1617 int nco =
nemhelper->write_complex_abs ? 3 : 2;
1618 std::vector<Real> complex_soln(nco * num_values);
1620 for (
unsigned i=0; i<num_vars; ++i)
1622 for (
unsigned int j=0; j<num_elems; ++j)
1625 complex_soln[nco*i*num_elems + j] =
value.real();
1627 for (
unsigned int j=0; j<num_elems; ++j)
1630 complex_soln[nco*i*num_elems + num_elems + j] =
value.imag();
1634 for (
unsigned int j=0; j<num_elems; ++j)
1637 complex_soln[3*i*num_elems + 2*num_elems + j] = std::abs(
value);
1647 nemhelper->initialize_global_variables( names );
1657 const std::vector<std::string> &)
1659 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1662 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1666 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 1670 libmesh_error_msg_if(!
nemhelper->opened_for_writing,
1671 "ERROR, Nemesis file must be initialized before outputting information records.");
1674 nemhelper->write_information_records( records );
1687 std::string system_var_name,
1688 std::string exodus_var_name,
1689 unsigned int timestep)
1691 libmesh_error_msg_if(!
nemhelper->opened_for_reading,
1692 "ERROR, Nemesis file must be opened for reading before copying a nodal solution!");
1694 nemhelper->read_nodal_var_values(exodus_var_name, timestep);
1698 for (
auto p :
nemhelper->nodal_var_values)
1703 if (node && node->
n_comp(system.
number(), var_num) > 0)
1709 system.
solution->set (dof_index, p.second);
1720 std::string system_var_name,
1721 std::string exodus_var_name,
1722 unsigned int timestep)
1724 parallel_object_only();
1728 "Error! Trying to copy elemental solution into a variable that is not of CONSTANT MONOMIAL type.");
1737 std::map<dof_id_type, Real> elem_var_value_map;
1739 libmesh_error_msg_if(!
nemhelper->opened_for_reading,
1740 "ERROR, Nemesis file must be opened for reading before copying an elemental solution!");
1742 nemhelper->read_elemental_var_values(exodus_var_name, timestep, elem_var_value_map);
1744 std::map<dof_id_type, Real>::iterator
1745 it = elem_var_value_map.begin(),
1746 end = elem_var_value_map.end();
1748 for (; it!=end; ++it)
1752 if (elem && elem->
n_comp(system.
number(), var_num) > 0)
1756 system.
solution->set (dof_index, it->second);
1763 parallel_object_only();
1769 std::vector<std::string> system_var_names,
1770 std::vector<std::string> exodus_var_names,
1771 unsigned int timestep)
1773 libmesh_error_msg_if(!
nemhelper->opened_for_reading,
1774 "ERROR, Nemesis file must be opened for reading before copying a scalar solution!");
1776 libmesh_error_msg_if(system_var_names.size() != exodus_var_names.size(),
1777 "ERROR, the number of system_var_names must match exodus_var_names.");
1779 std::vector<Real> values_from_exodus;
1790 std::vector<dof_id_type> SCALAR_dofs;
1793 system.
solution->set (SCALAR_dofs[0], values_from_exodus[i]);
1803 unsigned int timestep,
1804 std::vector<Real> & global_values)
1806 std::size_t size = global_var_names.size();
1807 libmesh_error_msg_if(size == 0,
"ERROR, empty list of global variables to read from the Nemesis file.");
1810 std::vector<Real> values_from_exodus;
1812 nemhelper->read_global_values(values_from_exodus, timestep);
1813 std::vector<std::string> global_var_names_exodus =
nemhelper->global_var_names;
1815 if (values_from_exodus.size() == 0)
1818 global_values.clear();
1819 for (std::size_t i = 0; i != size; ++i)
1823 auto it = find(global_var_names_exodus.begin(), global_var_names_exodus.end(), global_var_names[i]);
1824 if (it != global_var_names_exodus.end())
1825 global_values.push_back(values_from_exodus[it - global_var_names_exodus.begin()]);
1827 libmesh_error_msg(
"ERROR, Global variable " << global_var_names[i] << \
1828 " not found in Nemesis file.");
1834 nemhelper->set_hdf5_writing(write_hdf5);
1841 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1846 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1854 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1859 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_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...
std::size_t n_boundary_conds() const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
unique_id_type & set_unique_id()
This is the EquationSystems class.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
unsigned int variable_scalar_number(std::string_view var, unsigned int component) const
void make_node_unique_ids_parallel_consistent(MeshBase &)
Assuming all unique_ids on local nodes are globally unique, and assuming all processor ids are parall...
void build_variable_names(std::vector< std::string > &var_names, const FEType *type=nullptr, const std::set< std::string > *system_names=nullptr) const
Fill the input vector var_names with the names of the variables for each system.
virtual Node *& set_node(const unsigned int i)
A Node is like a Point, but with more information.
virtual unique_id_type parallel_max_unique_id() const =0
std::string & nodeset_name(boundary_id_type id)
virtual void read(const std::string &base_filename) override
Implements reading the mesh from several different files.
unsigned int n_comp(const unsigned int s, const unsigned int var) const
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
std::size_t n_edge_conds() const
void copy_nodal_solution(System &system, std::string system_var_name, std::string exodus_var_name, unsigned int timestep=1)
If we read in a nodal solution while reading in a mesh, we can attempt to copy that nodal solution in...
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
void deallocate(std::vector< T > &vec)
A convenient method to truly empty a vector using the "swap trick".
void alltoall(std::vector< T, A > &r) const
This is the base class from which all geometric element types are derived.
void write_information_records(const std::vector< std::string > &)
Write out information records.
const Parallel::Communicator & comm() const
void read_global_variable(std::vector< std::string > global_var_names, unsigned int timestep, std::vector< Real > &global_values)
Given a vector of global variables and a time step, returns the values of the global variable at the ...
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.
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.
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
bool _verbose
Controls whether extra debugging information is printed to the screen or not.
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...
uint8_t processor_id_type
This is the MeshBase class.
unsigned int variable_number(std::string_view var) const
This class handles the numbering of degrees of freedom on a mesh.
void get_vars_active_subdomains(const std::vector< std::string > &names, std::vector< std::set< subdomain_id_type >> &vars_active_subdomains) const
Retrieve vars_active_subdomains, which indicates the active subdomains for each variable in names...
This is the Nemesis_IO_Helper class.
virtual ~Nemesis_IO()
Destructor.
processor_id_type n_processors() const
virtual bool is_serial() const
void libmesh_ignore(const Args &...)
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
unsigned int number() const
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
void write_timestep(const std::string &fname, const EquationSystems &es, const int timestep, const Real time)
Write one timestep's worth of the solution.
This is the MeshCommunication class.
void prepare_to_write_nodal_data(const std::string &fname, const std::vector< std::string > &names)
Helper function containing code shared between the two different versions of write_nodal_data which t...
Manages consistently variables, degrees of freedom, and coefficient vectors.
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)
void allgather(MeshBase &mesh) const
This method takes an input DistributedMesh which may be distributed among all the processors...
void write_element_data(const EquationSystems &es)
Write out element solution in parallel, without localizing the solution vector.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
bool _append
Default false.
const std::vector< std::string > & get_nodal_var_names()
Return list of the nodal variable names.
std::string & subdomain_name(subdomain_id_type id)
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
void copy_scalar_solution(System &system, std::vector< std::string > system_var_names, std::vector< std::string > exodus_var_names, unsigned int timestep=1)
Copy global variables into scalar variables of a System object.
virtual dof_id_type parallel_n_nodes() const =0
bool _allow_empty_variables
If true, _output_variables is allowed to remain empty.
An object whose state is distributed along a set of processors.
virtual dof_id_type parallel_n_elem() const =0
void gather_neighboring_elements(DistributedMesh &) const
std::string & sideset_name(boundary_id_type id)
virtual void write_nodal_data(const std::string &fname, const std::vector< Number > &soln, const std::vector< std::string > &names) override
Output a nodal solution from data in soln.
void assert_symmetric_cmaps()
virtual const Elem * elem_ptr(const dof_id_type i) const =0
virtual void update()
Update the local values to reflect the solution on neighboring processors.
int _timestep
Keeps track of the current timestep index being written.
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
void max(const T &r, T &o, Request &req) const
void write_global_data(const std::vector< Number > &, const std::vector< std::string > &)
Write out global variables.
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 copy_elemental_solution(System &system, std::string system_var_name, std::string exodus_var_name, unsigned int timestep=1)
If we read in a elemental solution while reading in a mesh, we can attempt to copy that elemental sol...
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
std::vector< std::pair< unsigned int, unsigned int > > find_variable_numbers(std::vector< std::string > &names, const FEType *type=nullptr, const std::vector< FEType > *types=nullptr) const
Finds system and variable numbers for any variables of 'type' or of 'types' corresponding to the entr...
virtual void write(const std::string &base_filename) override
This method implements writing a mesh to a specified file.
void append(bool val)
If true, this flag will cause the Nemesis_IO object to attempt to open an existing file for writing...
std::unique_ptr< Nemesis_IO_Helper > nemhelper
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
void set_output_variables(const std::vector< std::string > &output_variables, bool allow_empty=true)
Specify the list of variables which should be included in the output (whitelist) If empty...
virtual void update_post_partitioning()
Recalculate any cached data after elements and nodes have been repartitioned.
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
Nemesis_IO(MeshBase &mesh, bool single_precision=false)
Constructor.
void set_hdf5_writing(bool write_hdf5)
Set to true (the default) to write files in an HDF5-based file format (when HDF5 is available)...
const DofMap & get_dof_map() const
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
void verbose(bool set_verbosity)
Set the flag indicating if we should be verbose.
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 write_complex_magnitude(bool val)
Set the flag indicating whether the complex modulus should be written when complex numbers are enable...
std::vector< std::string > _output_variables
The names of the variables to be output.
virtual dof_id_type n_nodes() const =0
bool local_index(dof_id_type dof_index) const