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 restrict_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 );
1699 libmesh_error_msg_if
1701 "ERROR, ExodusII file must be opened for reading before calling Nemesis_IO::get_time_steps()!");
1710 libmesh_error_msg_if(!
nemhelper->opened_for_reading && !
nemhelper->opened_for_writing,
1711 "ERROR, ExodusII file must be opened for reading or writing before calling Nemesis_IO::get_num_time_steps()!");
1719 std::string system_var_name,
1720 std::string exodus_var_name,
1721 unsigned int timestep)
1723 libmesh_error_msg_if(!
nemhelper->opened_for_reading,
1724 "ERROR, Nemesis file must be opened for reading before copying a nodal solution!");
1726 nemhelper->read_nodal_var_values(exodus_var_name, timestep);
1730 for (
auto p :
nemhelper->nodal_var_values)
1735 if (node && node->
n_comp(system.
number(), var_num) > 0)
1741 system.
solution->set (dof_index, p.second);
1752 std::string system_var_name,
1753 std::string exodus_var_name,
1754 unsigned int timestep)
1756 parallel_object_only();
1760 "Error! Trying to copy elemental solution into a variable that is not of CONSTANT MONOMIAL type.");
1769 std::map<dof_id_type, Real> elem_var_value_map;
1771 libmesh_error_msg_if(!
nemhelper->opened_for_reading,
1772 "ERROR, Nemesis file must be opened for reading before copying an elemental solution!");
1774 nemhelper->read_elemental_var_values(exodus_var_name, timestep, elem_var_value_map);
1776 std::map<dof_id_type, Real>::iterator
1777 it = elem_var_value_map.begin(),
1778 end = elem_var_value_map.end();
1780 for (; it!=end; ++it)
1784 if (elem && elem->
n_comp(system.
number(), var_num) > 0)
1788 system.
solution->set (dof_index, it->second);
1795 parallel_object_only();
1801 std::vector<std::string> system_var_names,
1802 std::vector<std::string> exodus_var_names,
1803 unsigned int timestep)
1805 libmesh_error_msg_if(!
nemhelper->opened_for_reading,
1806 "ERROR, Nemesis file must be opened for reading before copying a scalar solution!");
1808 libmesh_error_msg_if(system_var_names.size() != exodus_var_names.size(),
1809 "ERROR, the number of system_var_names must match exodus_var_names.");
1811 std::vector<Real> values_from_exodus;
1822 std::vector<dof_id_type> SCALAR_dofs;
1825 system.
solution->set (SCALAR_dofs[0], values_from_exodus[i]);
1835 unsigned int timestep,
1836 std::vector<Real> & global_values)
1838 std::size_t size = global_var_names.size();
1839 libmesh_error_msg_if(size == 0,
"ERROR, empty list of global variables to read from the Nemesis file.");
1842 std::vector<Real> values_from_exodus;
1844 nemhelper->read_global_values(values_from_exodus, timestep);
1845 std::vector<std::string> global_var_names_exodus =
nemhelper->global_var_names;
1847 if (values_from_exodus.size() == 0)
1850 global_values.clear();
1851 for (std::size_t i = 0; i != size; ++i)
1855 auto it = find(global_var_names_exodus.begin(), global_var_names_exodus.end(), global_var_names[i]);
1856 if (it != global_var_names_exodus.end())
1857 global_values.push_back(values_from_exodus[it - global_var_names_exodus.begin()]);
1859 libmesh_error_msg(
"ERROR, Global variable " << global_var_names[i] << \
1860 " not found in Nemesis file.");
1869 libmesh_experimental();
1876 nemhelper->set_hdf5_writing(write_hdf5);
1883 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1888 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1896 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1904 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1912 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1917 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1924 libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
1929 #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
virtual void update_post_partitioning()
Recalculate any cached data (or invalidate any caches that are computed on the fly) after elements an...
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
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...
const std::vector< std::string > & get_global_var_names()
Return list of the global variable names.
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.
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
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...
const std::vector< std::string > & get_elem_var_names()
Return list of the elemental variable names.
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
const std::vector< Real > & get_time_steps()
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
Nemesis_IO_Helper & get_nemio_helper()
Return a reference to the Nemesis_IO_Helper object.
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