23 #include "libmesh/distributed_mesh.h" 
   24 #include "libmesh/elem.h" 
   25 #include "libmesh/exodusII_io.h" 
   26 #include "libmesh/libmesh_logging.h" 
   27 #include "libmesh/nemesis_io.h" 
   28 #include "libmesh/nemesis_io_helper.h" 
   29 #include "libmesh/node.h" 
   30 #include "libmesh/parallel.h" 
   31 #include "libmesh/utility.h"  
   32 #include "libmesh/boundary_info.h" 
   33 #include "libmesh/mesh_communication.h" 
   34 #include "libmesh/fe_type.h" 
   35 #include "libmesh/equation_systems.h" 
   36 #include "libmesh/numeric_vector.h" 
   37 #include "libmesh/int_range.h" 
   38 #include "libmesh/auto_ptr.h" 
   47 struct CompareGlobalIdxMappings
 
   51   bool operator()(
const std::pair<unsigned int, unsigned int> & a,
 
   52                   const std::pair<unsigned int, unsigned int> & b)
 const 
   53   { 
return a.first < b.first; }
 
   57   bool operator()(
const std::pair<unsigned int, unsigned int> & a,
 
   58                   const unsigned int b)
 const 
   59   { 
return a.first < b; }
 
   67 inline unsigned int to_uint ( 
const T & t )
 
   69   libmesh_assert_equal_to (t, static_cast<T>(static_cast<unsigned int>(t)));
 
   71   return static_cast<unsigned int>(t);
 
   76 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) && !defined(NDEBUG) 
   77 inline bool global_idx_mapping_equality (
const std::pair<unsigned int, unsigned int> & a,
 
   78                                          const std::pair<unsigned int, unsigned int> & b)
 
   80   return a.first == b.first;
 
   91 #
if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
 
  100 #
if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
 
  101   nemhelper(libmesh_make_unique<
Nemesis_IO_Helper>(*this, false, single_precision)),
 
  106   _allow_empty_variables(false)
 
  124 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
  149 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
  165   LOG_SCOPE (
"read()",
"Nemesis_IO");
 
  168   parallel_object_only();
 
  178   std::string nemesis_filename = 
nemhelper->construct_nemesis_filename(base_filename);
 
  181     libMesh::out << 
"Opening file: " << nemesis_filename << std::endl;
 
  184   nemhelper->open(nemesis_filename.c_str(), 
true);
 
  215     libmesh_error_msg(
"ERROR: there should be no external nodes in an element-based partitioning!");
 
  217   libmesh_assert_equal_to (
nemhelper->num_nodes,
 
  221   libmesh_assert_equal_to (
nemhelper->num_elem,
 
  255   libmesh_assert_equal_to (to_uint(
nemhelper->num_node_cmaps), 
nemhelper->node_cmap_node_cnts.size());
 
  256   libmesh_assert_equal_to (to_uint(
nemhelper->num_node_cmaps), 
nemhelper->node_cmap_node_ids.size());
 
  257   libmesh_assert_equal_to (to_uint(
nemhelper->num_node_cmaps), 
nemhelper->node_cmap_proc_ids.size());
 
  265     std::vector<unsigned char> pid_send_partner (this->
n_processors(), 0);
 
  271     for (
unsigned int cmap=0; cmap<to_uint(
nemhelper->num_node_cmaps); cmap++)
 
  273         libmesh_assert_less (
nemhelper->node_cmap_ids[cmap], this->n_processors());
 
  275         pid_send_partner[
nemhelper->node_cmap_ids[cmap]] = 1;
 
  280     const std::vector<unsigned char> pid_recv_partner (pid_send_partner);
 
  282     this->
comm().alltoall (pid_send_partner);
 
  292   std::vector<processor_id_type> node_ownership (
nemhelper->num_internal_nodes +
 
  294                                                  this->processor_id());
 
  297   std::map<unsigned int, unsigned int> pid_to_cmap_map;
 
  300   for (
unsigned int cmap=0; cmap<to_uint(
nemhelper->num_node_cmaps); cmap++)
 
  303       libmesh_assert_equal_to (to_uint(
nemhelper->node_cmap_node_cnts[cmap]),
 
  304                                nemhelper->node_cmap_node_ids[cmap].size());
 
  306       libmesh_assert_equal_to (to_uint(
nemhelper->node_cmap_node_cnts[cmap]),
 
  307                                nemhelper->node_cmap_proc_ids[cmap].size());
 
  312         cast_int<processor_id_type>(
nemhelper->node_cmap_ids[cmap]);
 
  314       libmesh_assert_less (adjcnt_pid_idx, this->
n_processors());
 
  315       libmesh_assert_not_equal_to (adjcnt_pid_idx, this->
processor_id());
 
  320       pid_to_cmap_map[adjcnt_pid_idx] = cmap;
 
  326           libmesh_assert_equal_to
 
  328              cast_int<processor_id_type>(
nemhelper->node_cmap_proc_ids[cmap][
idx]));
 
  331           const unsigned int local_node_idx = 
nemhelper->node_cmap_node_ids[cmap][
idx]-1;
 
  333           libmesh_assert_less (local_node_idx, node_ownership.size());
 
  337           node_ownership[local_node_idx] =
 
  338             std::min(node_ownership[local_node_idx], adjcnt_pid_idx);
 
  344   unsigned int num_nodes_i_must_number = 0;
 
  346   for (
const auto & pid : node_ownership)
 
  348       num_nodes_i_must_number++;
 
  351   libmesh_assert_greater_equal (num_nodes_i_must_number, 
nemhelper->num_internal_nodes);
 
  356                  << 
"num_nodes_i_must_number=" 
  357                  << num_nodes_i_must_number
 
  364   std::vector<int> all_loadbal_data ( 8 );
 
  365   all_loadbal_data[0] = 
nemhelper->num_internal_nodes;
 
  366   all_loadbal_data[1] = 
nemhelper->num_border_nodes;
 
  367   all_loadbal_data[2] = 
nemhelper->num_external_nodes;
 
  368   all_loadbal_data[3] = 
nemhelper->num_internal_elems;
 
  369   all_loadbal_data[4] = 
nemhelper->num_border_elems;
 
  370   all_loadbal_data[5] = 
nemhelper->num_node_cmaps;
 
  371   all_loadbal_data[6] = 
nemhelper->num_elem_cmaps;
 
  372   all_loadbal_data[7] = num_nodes_i_must_number;
 
  374   this->
comm().allgather (all_loadbal_data,  
true);
 
  380   Parallel::MessageTag nodes_tag = 
mesh.
comm().get_unique_tag();
 
  382   std::vector<std::vector<int>>
 
  383     needed_node_idxs (
nemhelper->num_node_cmaps); 
 
  385   std::vector<Parallel::Request>
 
  386     needed_nodes_requests (
nemhelper->num_node_cmaps);
 
  388   for (
unsigned int cmap=0; cmap<to_uint(
nemhelper->num_node_cmaps); cmap++)
 
  394       needed_node_idxs[cmap].reserve   (
nemhelper->node_cmap_node_cnts[cmap]);
 
  396       const unsigned int adjcnt_pid_idx = 
nemhelper->node_cmap_ids[cmap];
 
  402             local_node_idx  = 
nemhelper->node_cmap_node_ids[cmap][
idx]-1,
 
  403             owning_pid_idx  = node_ownership[local_node_idx];
 
  406           if (owning_pid_idx == adjcnt_pid_idx)
 
  409                 global_node_idx = 
nemhelper->node_num_map[local_node_idx]-1;
 
  410               needed_node_idxs[cmap].push_back(global_node_idx);
 
  414       this->
comm().send (adjcnt_pid_idx,              
 
  415                          needed_node_idxs[cmap],      
 
  416                          needed_nodes_requests[cmap], 
 
  424   std::vector<unsigned int>
 
  428     all_num_nodes_i_must_number[pid] = all_loadbal_data[8*pid + 7];
 
  431   libmesh_assert (std::accumulate(all_num_nodes_i_must_number.begin(),
 
  432                                   all_num_nodes_i_must_number.end(),
 
  435   unsigned int my_next_node = 0;
 
  437     my_next_node += all_num_nodes_i_must_number[pid];
 
  439   const unsigned int my_node_offset = my_next_node;
 
  449   for (
unsigned int i=0; i<to_uint(
nemhelper->num_internal_nodes); ++i)
 
  451       const unsigned int local_node_idx  = 
nemhelper->node_mapi[i]-1;
 
  453       const unsigned int owning_pid_idx  = node_ownership[local_node_idx];
 
  457       libmesh_assert_equal_to (owning_pid_idx, this->
processor_id());
 
  458       libmesh_assert_less (my_next_node, 
nemhelper->num_nodes_global);
 
  467                         this->processor_id());
 
  470       if (added_node->
id() != my_next_node)
 
  473                        << 
", but we wanted ID " << my_next_node << std::endl;
 
  478       nemhelper->node_num_map[local_node_idx] = my_next_node++;
 
  486   typedef std::vector<std::pair<unsigned int, unsigned int>> global_idx_mapping_type;
 
  487   global_idx_mapping_type old_global_to_new_global_map;
 
  488   old_global_to_new_global_map.reserve (num_nodes_i_must_number 
 
  491   CompareGlobalIdxMappings global_idx_mapping_comp;
 
  493   for (
unsigned int i=0; i<to_uint(
nemhelper->num_border_nodes); ++i)
 
  496         local_node_idx  = 
nemhelper->node_mapb[i]-1,
 
  497         owning_pid_idx  = node_ownership[local_node_idx];
 
  503             global_node_idx = 
nemhelper->node_num_map[local_node_idx]-1;
 
  507           old_global_to_new_global_map.push_back(std::make_pair(global_node_idx,
 
  517                             this->processor_id());
 
  520           if (added_node->
id() != my_next_node)
 
  523                            << 
", but we wanted ID " << my_next_node << std::endl;
 
  528           nemhelper->node_num_map[local_node_idx] = my_next_node++;
 
  532   libmesh_assert_equal_to (num_nodes_i_must_number, (my_next_node - my_node_offset));
 
  535   std::sort (old_global_to_new_global_map.begin(),
 
  536              old_global_to_new_global_map.end(),
 
  537              global_idx_mapping_comp);
 
  540   libmesh_assert (std::unique (old_global_to_new_global_map.begin(),
 
  541                                old_global_to_new_global_map.end(),
 
  542                                global_idx_mapping_equality) ==
 
  543                   old_global_to_new_global_map.end());
 
  547   std::map<unsigned int, std::vector<int>> requested_node_idxs; 
 
  549   std::vector<Parallel::Request> requested_nodes_requests(
nemhelper->num_node_cmaps);
 
  558   std::vector<bool> processed_cmap (
nemhelper->num_node_cmaps, 
false);
 
  560   for (
unsigned int comm_step=0; comm_step<2*to_uint(
nemhelper->num_node_cmaps); comm_step++)
 
  563       const Parallel::Status
 
  564         status (this->
comm().probe (Parallel::any_source,
 
  567         requesting_pid_idx = status.source(),
 
  568         source_pid_idx     = status.source();
 
  574       const unsigned int cmap = pid_to_cmap_map[source_pid_idx];
 
  576       if (!processed_cmap[cmap])
 
  578           processed_cmap[cmap] = 
true;
 
  585           std::vector<int> & xfer_buf (requested_node_idxs[requesting_pid_idx]);
 
  588           this->
comm().receive (requesting_pid_idx, xfer_buf, nodes_tag);
 
  594               const unsigned int old_global_node_idx = xfer_buf[i];
 
  599               const global_idx_mapping_type::const_iterator it =
 
  600                 std::lower_bound (old_global_to_new_global_map.begin(),
 
  601                                   old_global_to_new_global_map.end(),
 
  603                                   global_idx_mapping_comp);
 
  606               libmesh_assert_equal_to (it->first, old_global_node_idx);
 
  607               libmesh_assert_greater_equal (it->second, my_node_offset);
 
  608               libmesh_assert_less (it->second, my_next_node);
 
  611               xfer_buf[i] = it->second;
 
  615           this->
comm().send (requesting_pid_idx,
 
  617                              requested_nodes_requests[cmap],
 
  633           libmesh_assert_equal_to (to_uint(
nemhelper->node_cmap_ids[cmap]), source_pid_idx);
 
  636           this->
comm().receive (source_pid_idx,
 
  637                                 needed_node_idxs[cmap],
 
  640           libmesh_assert_less_equal (needed_node_idxs[cmap].size(),
 
  641                                      nemhelper->node_cmap_node_ids[cmap].size());
 
  643           for (std::size_t i=0, j=0, ncnis=
nemhelper->node_cmap_node_ids[cmap].size(); i < ncnis; i++)
 
  646                 local_node_idx  = 
nemhelper->node_cmap_node_ids[cmap][i]-1,
 
  647                 owning_pid_idx  = node_ownership[local_node_idx];
 
  651               if (owning_pid_idx == source_pid_idx)
 
  653                   libmesh_assert_less (j, needed_node_idxs[cmap].size());
 
  656                     global_node_idx = needed_node_idxs[cmap][j++];
 
  664                                     cast_int<dof_id_type>(global_node_idx),
 
  665                                     cast_int<processor_id_type>(source_pid_idx));
 
  668                   if (added_node->
id() != global_node_idx)
 
  671                                    << 
", but we wanted ID " << global_node_idx << std::endl;
 
  676                   nemhelper->node_num_map[local_node_idx] = global_node_idx;
 
  688   libmesh_assert_equal_to ((my_next_node - my_node_offset), to_uint(
nemhelper->num_nodes));
 
  708   Parallel::wait (needed_nodes_requests);
 
  709   Parallel::wait (requested_nodes_requests);
 
  710   requested_node_idxs.clear();
 
  738     int sum_internal_elems=0, sum_border_elems=0;
 
  739     for (
unsigned int j=3,c=0; c<this->
n_processors(); j+=8,++c)
 
  740       sum_internal_elems += all_loadbal_data[j];
 
  742     for (
unsigned int j=4,c=0; c<this->
n_processors(); j+=8,++c)
 
  743       sum_border_elems += all_loadbal_data[j];
 
  748         libMesh::out << 
"sum_internal_elems=" << sum_internal_elems << std::endl;
 
  751         libMesh::out << 
"sum_border_elems=" << sum_border_elems << std::endl;
 
  754     libmesh_assert_equal_to (sum_internal_elems+sum_border_elems, 
nemhelper->num_elems_global);
 
  770   unsigned int my_next_elem = 0;
 
  772     my_next_elem += (all_loadbal_data[8*pid + 3]+  
 
  773                      all_loadbal_data[8*pid + 4]); 
 
  774   const unsigned int my_elem_offset = my_next_elem;
 
  778                  << 
"my_elem_offset=" << my_elem_offset << std::endl;
 
  812   for (
unsigned int i=0; i<to_uint(
nemhelper->num_elem_blk); i++)
 
  824       if (!
nemhelper->num_elem_this_blk) 
continue;
 
  828         cast_int<subdomain_id_type>(
nemhelper->block_ids[i]);
 
  831       const std::string type_str ( 
nemhelper->elem_type.data() );
 
  834       const auto & conv = 
nemhelper->get_conversion(type_str);
 
  837         libMesh::out << 
"Reading a block of " << type_str << 
" elements." << std::endl;
 
  840       for (
unsigned int j=0; j<to_uint(
nemhelper->num_elem_this_blk); j++)
 
  851           elem->
set_id()       = my_next_elem++;
 
  852 #ifdef LIBMESH_ENABLE_UNIQUE_ID 
  867           if (elem->
id() != my_next_elem-1)
 
  868             libmesh_error_msg(
"Unexpected ID "  \
 
  870                               << 
" set by parallel mesh. (expecting "   \
 
  877                          << 
"Setting nodes for Elem " << elem->
id() << std::endl;
 
  879           for (
unsigned int k=0; k<to_uint(
nemhelper->num_nodes_per_elem); k++)
 
  883                                    conv.get_node_map(k)),
 
  884                 local_node_idx  = 
nemhelper->connect[gi]-1,                
 
  885                 global_node_idx = 
nemhelper->node_num_map[local_node_idx]; 
 
  893   libmesh_assert_equal_to ((my_next_elem - my_elem_offset), to_uint(
nemhelper->num_elem));
 
  904   unsigned char max_dim_seen = 0;
 
  907       max_dim_seen = static_cast<unsigned char>(i);
 
  912   this->
comm().max(max_dim_seen);
 
  918                    << 
"max_dim_seen=" << +max_dim_seen << std::endl;
 
  926     libmesh_error_msg(
"Cannot open dimension "   \
 
  928                       << 
" mesh file when configured without "          \
 
  940                    << 
"Read global sideset parameter information." << std::endl;
 
  944                    << 
"Number of global sideset IDs: " << 
nemhelper->global_sideset_ids.size() << std::endl;
 
  961                    << 
"nemhelper->num_side_sets = " << 
nemhelper->num_side_sets << std::endl;
 
  964                    << 
"nemhelper->num_elem_all_sidesets = " << 
nemhelper->num_elem_all_sidesets << std::endl;
 
  969           for (
const auto & pr : 
nemhelper->id_to_ss_names)
 
  970             libMesh::out << 
"(" << pr.first << 
"," << pr.second << 
") ";
 
  981     int sum_num_global_side_counts = std::accumulate(
nemhelper->num_global_side_counts.begin(),
 
  986     int sum_num_elem_all_sidesets = 
nemhelper->num_elem_all_sidesets;
 
  987     this->
comm().sum(sum_num_elem_all_sidesets);
 
  989     if (sum_num_global_side_counts != sum_num_elem_all_sidesets)
 
  990       libmesh_error_msg(
"Error! global side count reported by Nemesis does not " \
 
  991                         << 
"match the side count reported by the individual files!");
 
  998   for (
int offset=0, i=0; i<
nemhelper->num_side_sets; i++)
 
 1000       offset += (i > 0 ? 
nemhelper->num_sides_per_set[i-1] : 0); 
 
 1046       const auto & conv = 
nemhelper->get_conversion(elem->
type());
 
 1052                                         cast_int<unsigned short>(conv.get_side_map(
nemhelper->side_list[e]-1)), 
 
 1053                                         cast_int<boundary_id_type>(
nemhelper->id_list[e]));
 
 1063     if (nbcs != 
nemhelper->elem_list.size())
 
 1064       libmesh_error_msg(
"[" << this->
processor_id() << 
"] "   \
 
 1065                         << 
"BoundaryInfo contains "                     \
 
 1067                         << 
" boundary conditions, while the Exodus file had " \
 
 1085           for (
const auto & pr : 
nemhelper->id_to_ns_names)
 
 1086             libMesh::out << 
"(" << pr.first << 
"," << pr.second << 
") ";
 
 1100   for (
int nodeset=0; nodeset<
nemhelper->num_node_sets; nodeset++)
 
 1103       int nodeset_id = 
nemhelper->nodeset_ids[nodeset];
 
 1108           libMesh::out << 
"nemhelper->nodeset_ids[" << nodeset << 
"]=" << nodeset_id << std::endl;
 
 1119             libmesh_error_msg(
"Error, index is past the end of node_num_map array!");
 
 1128                            << 
"nodeset " << nodeset
 
 1129                            << 
", local node number: " << 
nemhelper->node_list[node]-1
 
 1130                            << 
", global node id: " << global_node_id
 
 1136             (cast_int<dof_id_type>(global_node_id),
 
 1137              cast_int<boundary_id_type>(nodeset_id));
 
 1172   libmesh_error_msg(
"ERROR, Nemesis API is not defined!");
 
 1175 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1181 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1189   std::string nemesis_filename = 
nemhelper->construct_nemesis_filename(base_filename);
 
 1196     libmesh_warning(
"Warning: Appending in Nemesis_IO::write() does not make sense.\n" 
 1197                     "Creating a new file instead!");
 
 1225     libmesh_warning(
"Warning: Mesh contains edge boundary IDs, but these " 
 1226                     "are not supported by the Nemesis format.");
 
 1233   libmesh_error_msg(
"ERROR, Nemesis API is not defined!");
 
 1236 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1239 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1249   nemhelper->write_timestep(timestep, time);
 
 1259   libmesh_error_msg(
"ERROR, Nemesis API is not defined!");
 
 1262 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1266 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1269                                               const std::vector<std::string> & names)
 
 1273   std::string nemesis_filename = 
nemhelper->construct_nemesis_filename(fname);
 
 1282           nemhelper->open(nemesis_filename.c_str(), 
false);
 
 1299             libmesh_warning(
"Warning: Mesh contains edge boundary IDs, but these " 
 1300                             "are not supported by the ExodusII format.");
 
 1308 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 
 1309   std::vector<std::string> complex_names = 
nemhelper->get_complex_names(names);
 
 1310   nemhelper->initialize_nodal_variables(complex_names);
 
 1312   nemhelper->initialize_nodal_variables(names);
 
 1319                                               const std::vector<std::string> &)
 
 1321   libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
 
 1328 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1332                                    const std::vector<std::string> & names)
 
 1334   LOG_SCOPE(
"write_nodal_data(parallel)", 
"Nemesis_IO");
 
 1339   std::vector<std::string> output_names;
 
 1344     output_names = names;
 
 1357                                    const std::set<std::string> * system_names)
 
 1359   LOG_SCOPE(
"write_nodal_data(parallel)", 
"Nemesis_IO");
 
 1364   std::vector<std::string> output_names;
 
 1373   std::vector<std::pair<unsigned int, unsigned int>> var_nums =
 
 1383                                    const std::vector<std::string> &)
 
 1385   libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
 
 1389                                    const EquationSystems &,
 
 1390                                    const std::set<std::string> *)
 
 1392   libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
 
 1399 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1404     libmesh_error_msg(
"ERROR, Nemesis file must be initialized before outputting elemental variables.");
 
 1407   std::vector<std::string> names;
 
 1416       std::vector<std::string> monomials;
 
 1423       for (
const auto & var : monomials)
 
 1425           names.push_back(var);
 
 1430   std::vector<std::pair<unsigned int, unsigned int>> var_nums =
 
 1436   if (var_nums.empty())
 
 1439         libMesh::out << 
"No CONSTANT, MONOMIAL data to be written." << std::endl;
 
 1446   std::vector<std::set<subdomain_id_type>> vars_active_subdomains;
 
 1456   nemhelper->initialize_element_variables(names, vars_active_subdomains);
 
 1467                                   vars_active_subdomains);
 
 1474   libmesh_not_implemented();
 
 1481 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1484                                    const std::vector<Number> & soln,
 
 1485                                    const std::vector<std::string> & names)
 
 1487   LOG_SCOPE(
"write_nodal_data(serialized)", 
"Nemesis_IO");
 
 1497                                    const std::vector<Number> &,
 
 1498                                    const std::vector<std::string> &)
 
 1500   libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
 
 1508 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1511                                     const std::vector<std::string> & names)
 
 1514     libmesh_error_msg(
"ERROR, Nemesis file must be initialized before outputting global variables.");
 
 1516 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 
 1518   std::vector<std::string> complex_names = 
nemhelper->get_complex_names(names);
 
 1520   nemhelper->initialize_global_variables(complex_names);
 
 1522   unsigned int num_values = soln.size();
 
 1523   unsigned int num_vars = names.size();
 
 1524   unsigned int num_elems = num_values / num_vars;
 
 1528   std::vector<Real> complex_soln(3*num_values);
 
 1530   for (
unsigned i=0; i<num_vars; ++i)
 
 1532       for (
unsigned int j=0; j<num_elems; ++j)
 
 1535           complex_soln[3*i*num_elems + j] = 
value.real();
 
 1537       for (
unsigned int j=0; j<num_elems; ++j)
 
 1540           complex_soln[3*i*num_elems + num_elems +j] = 
value.imag();
 
 1542       for (
unsigned int j=0; j<num_elems; ++j)
 
 1545           complex_soln[3*i*num_elems + 2*num_elems + j] = 
std::abs(
value);
 
 1554   nemhelper->initialize_global_variables( names );
 
 1564                                     const std::vector<std::string> &)
 
 1566   libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
 
 1569 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1573 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API) 
 1578     libmesh_error_msg(
"ERROR, Nemesis file must be initialized before outputting information records.");
 
 1581   nemhelper->write_information_records( records );
 
 1589   libmesh_error_msg(
"ERROR, Nemesis API is not defined.");
 
 1592 #endif // #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)