libMesh
Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
libMesh::TecplotIO Class Reference

This class implements writing meshes in the Tecplot format. More...

#include <tecplot_io.h>

Inheritance diagram for libMesh::TecplotIO:
[legend]

Public Member Functions

 TecplotIO (const MeshBase &, const bool binary=false, const double time=0., const int strand_offset=0)
 Constructor. More...
 
virtual void write (const std::string &) override
 This method implements writing a mesh to a specified file. More...
 
virtual void write_nodal_data (const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
 This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are provided. More...
 
bool & binary ()
 Flag indicating whether or not to write a binary file (if the tecio.a library was found by configure). More...
 
double & time ()
 Solution time for transient data. More...
 
intstrand_offset ()
 Strand offset for this file. More...
 
std::string & zone_title ()
 The zone title to write. More...
 
bool & ascii_append ()
 Set to true to write multiple solutions to a single file (ASCII only). More...
 
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 EquationSystems object. More...
 
virtual void write_discontinuous_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
 This method implements writing a mesh with discontinuous data to a specified file where the data is taken from the EquationSystems object. More...
 
virtual void write_nodal_data (const std::string &, const NumericVector< Number > &, const std::vector< std::string > &)
 This method may be overridden by "parallel" output formats for writing nodal data. More...
 
virtual void write_nodal_data (const std::string &, const EquationSystems &, const std::set< std::string > *)
 This method should be overridden by "parallel" output formats for writing nodal data. More...
 
virtual void write_nodal_data_discontinuous (const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
 This method implements writing a mesh with discontinuous data to a specified file where the nodal data and variables names are provided. More...
 
unsigned intascii_precision ()
 Return/set the precision to use when writing ASCII files. More...
 

Protected Member Functions

const MeshBasemesh () const
 
virtual bool get_add_sides ()
 

Protected Attributes

const bool _is_parallel_format
 Flag specifying whether this format is parallel-capable. More...
 
const bool _serial_only_needed_on_proc_0
 Flag specifying whether this format can be written by only serializing the mesh to processor zero. More...
 

Private Member Functions

void write_ascii (const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
 This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are optionally provided. More...
 
void write_binary (const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
 This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are optionally provided. More...
 
unsigned elem_dimension ()
 Determines the logical spatial dimension of the elements in the Mesh. More...
 

Private Attributes

bool _binary
 Flag to write binary data. More...
 
double _time
 Solution time. More...
 
int _strand_offset
 Offset for Tecplot's STRANDID. More...
 
std::string _zone_title
 The zone title to write. More...
 
bool _ascii_append
 If true, when writing in ASCII format, open the file in std::ofstream::app mode. More...
 
std::set< subdomain_id_type_subdomain_ids
 The subdomains in the mesh. More...
 

Detailed Description

This class implements writing meshes in the Tecplot format.

Author
Benjamin S. Kirk
Date
2004

Definition at line 43 of file tecplot_io.h.

Constructor & Destructor Documentation

◆ TecplotIO()

libMesh::TecplotIO::TecplotIO ( const MeshBase mesh_in,
const bool  binary = false,
const double  time = 0.,
const int  strand_offset = 0 
)
explicit

Constructor.

Takes a reference to a constant mesh object. This constructor will only allow us to write the mesh. The optional parameter binary can be used to switch between ASCII (false, the default) or binary (true) output files.

Definition at line 121 of file tecplot_io.C.

References _subdomain_ids, and libMesh::MeshBase::subdomain_ids().

124  :
125  MeshOutput<MeshBase> (mesh_in),
126  _binary (binary_in),
127  _time (time_in),
128  _strand_offset (strand_offset_in),
129  _zone_title ("zone"),
130  _ascii_append(false)
131 {
132  // Gather a list of subdomain ids in the mesh.
133  // We must do this now, while we have every
134  // processor's attention
135  // (some of the write methods only execute on processor 0).
136  mesh_in.subdomain_ids (_subdomain_ids);
137 }
double _time
Solution time.
Definition: tecplot_io.h:151
template class LIBMESH_EXPORT MeshOutput< MeshBase >
Definition: mesh_output.C:180
bool _binary
Flag to write binary data.
Definition: tecplot_io.h:146
std::set< subdomain_id_type > _subdomain_ids
The subdomains in the mesh.
Definition: tecplot_io.h:172
int _strand_offset
Offset for Tecplot&#39;s STRANDID.
Definition: tecplot_io.h:156
bool _ascii_append
If true, when writing in ASCII format, open the file in std::ofstream::app mode.
Definition: tecplot_io.h:167
std::string _zone_title
The zone title to write.
Definition: tecplot_io.h:161

Member Function Documentation

◆ ascii_append()

bool & libMesh::TecplotIO::ascii_append ( )

Set to true to write multiple solutions to a single file (ASCII only).

Tecplot will read multiple zones in a single file, but currently you have to repeat the mesh information each time.

Definition at line 168 of file tecplot_io.C.

References _ascii_append.

169 {
170  return _ascii_append;
171 }
bool _ascii_append
If true, when writing in ASCII format, open the file in std::ofstream::app mode.
Definition: tecplot_io.h:167

◆ ascii_precision()

unsigned int & libMesh::MeshOutput< MeshBase >::ascii_precision ( )
inlineinherited

Return/set the precision to use when writing ASCII files.

By default we use numeric_limits<Real>::max_digits10, which should be enough to write out to ASCII and get the exact same Real back when reading in.

Definition at line 269 of file mesh_output.h.

Referenced by libMesh::UNVIO::nodes_out(), libMesh::FroIO::write(), libMesh::MEDITIO::write_ascii(), write_ascii(), libMesh::GMVIO::write_ascii_new_impl(), and libMesh::GMVIO::write_ascii_old_impl().

270 {
271  return _ascii_precision;
272 }
unsigned int _ascii_precision
Precision to use when writing ASCII files.
Definition: mesh_output.h:207

◆ binary()

bool & libMesh::TecplotIO::binary ( )

Flag indicating whether or not to write a binary file (if the tecio.a library was found by configure).

Definition at line 141 of file tecplot_io.C.

References _binary.

Referenced by write(), and write_nodal_data().

142 {
143  return _binary;
144 }
bool _binary
Flag to write binary data.
Definition: tecplot_io.h:146

◆ elem_dimension()

unsigned libMesh::TecplotIO::elem_dimension ( )
private

Determines the logical spatial dimension of the elements in the Mesh.

Ex: A 1D edge element living in 3D is a logically one-dimensional element as far as Tecplot is concerned. Throws an error if mixed-dimension element types are found, since I'm not sure how to handle that case currently.

Definition at line 204 of file tecplot_io.C.

References libMesh::MeshOutput< MT >::mesh().

Referenced by write_ascii(), and write_binary().

205 {
206  // Get a constant reference to the mesh.
207  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
208 
209  std::vector<unsigned> elem_dims(3);
210 
211  // Loop over all the elements and mark the proper dimension entry in
212  // the elem_dims vector.
213  for (const auto & elem : the_mesh.active_element_ptr_range())
214  elem_dims[elem->dim() - 1] = 1;
215 
216  // Detect and disallow (for now) the writing of mixed dimension meshes.
217  libmesh_error_msg_if(std::count(elem_dims.begin(), elem_dims.end(), 1) > 1,
218  "Error, cannot write Mesh with mixed element dimensions to Tecplot file!");
219 
220  if (elem_dims[0])
221  return 1;
222  else if (elem_dims[1])
223  return 2;
224  else if (elem_dims[2])
225  return 3;
226  else
227  libmesh_error_msg("No 1, 2, or 3D elements detected!");
228 }
const MT & mesh() const
Definition: mesh_output.h:259

◆ get_add_sides()

virtual bool libMesh::MeshOutput< MeshBase >::get_add_sides ( )
inlineprotectedvirtualinherited
Returns
Whether or not added sides are expected to be output, to plot SIDE_DISCONTINUOUS data. Subclasses should override this if they are capable of plotting such data.

Reimplemented in libMesh::ExodusII_IO.

Definition at line 176 of file mesh_output.h.

176 { return false; }

◆ mesh()

const MeshBase & libMesh::MeshOutput< MeshBase >::mesh ( ) const
inlineprotectedinherited
Returns
The object as a read-only reference.

Definition at line 259 of file mesh_output.h.

References libMesh::libmesh_assert().

Referenced by libMesh::FroIO::write(), write(), libMesh::MEDITIO::write(), libMesh::PostscriptIO::write(), libMesh::EnsightIO::write(), write_ascii(), write_binary(), write_nodal_data(), libMesh::MEDITIO::write_nodal_data(), and libMesh::GnuPlotIO::write_solution().

260 {
262  return *_obj;
263 }
const MeshBase *const _obj
A pointer to a constant object.
Definition: mesh_output.h:202
libmesh_assert(ctx)

◆ strand_offset()

int & libMesh::TecplotIO::strand_offset ( )

Strand offset for this file.

Each mesh block will be written to (strand_id=block_id+1+strand_offset). Written to newer binary formats that are time-aware, defaults to 0.

Definition at line 155 of file tecplot_io.C.

References _strand_offset.

Referenced by write_binary().

156 {
157  return _strand_offset;
158 }
int _strand_offset
Offset for Tecplot&#39;s STRANDID.
Definition: tecplot_io.h:156

◆ time()

double & libMesh::TecplotIO::time ( )

Solution time for transient data.

Written to newer binary formats that are time-aware.

Definition at line 148 of file tecplot_io.C.

References _time.

149 {
150  return _time;
151 }
double _time
Solution time.
Definition: tecplot_io.h:151

◆ write()

void libMesh::TecplotIO::write ( const std::string &  fname)
overridevirtual

This method implements writing a mesh to a specified file.

Implements libMesh::MeshOutput< MeshBase >.

Definition at line 174 of file tecplot_io.C.

References binary(), libMesh::MeshOutput< MeshBase >::mesh(), write_ascii(), and write_binary().

Referenced by libMesh::NameBasedIO::write().

175 {
176  if (this->mesh().processor_id() == 0)
177  {
178  if (this->binary())
179  this->write_binary (fname);
180  else
181  this->write_ascii (fname);
182  }
183 }
const MeshBase & mesh() const
Definition: mesh_output.h:259
bool & binary()
Flag indicating whether or not to write a binary file (if the tecio.a library was found by configure)...
Definition: tecplot_io.C:141
void write_ascii(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: tecplot_io.C:232
void write_binary(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: tecplot_io.C:351

◆ write_ascii()

void libMesh::TecplotIO::write_ascii ( const std::string &  fname,
const std::vector< Number > *  v = nullptr,
const std::vector< std::string > *  solution_names = nullptr 
)
private

This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are optionally provided.

This will write an ASCII file.

Definition at line 232 of file tecplot_io.C.

References _ascii_append, _time, std::abs(), libMesh::MeshOutput< MeshBase >::ascii_precision(), elem_dimension(), libMesh::make_range(), libMesh::MeshOutput< MT >::mesh(), libMesh::MeshOutput< MeshBase >::mesh(), libMesh::MeshBase::n_active_sub_elem(), libMesh::MeshBase::n_nodes(), n_vars, libMesh::out, libMesh::MeshBase::point(), libMesh::TECPLOT, and libMesh::TypeVector< T >::write_unformatted().

Referenced by write(), write_binary(), and write_nodal_data().

235 {
236  // Should only do this on processor 0!
237  libmesh_assert_equal_to (this->mesh().processor_id(), 0);
238 
239  // Create an output stream, possibly in append mode.
240  std::ofstream out_stream(fname.c_str(), _ascii_append ? std::ofstream::app : std::ofstream::out);
241 
242  // Make sure it opened correctly
243  if (!out_stream.good())
244  libmesh_file_error(fname.c_str());
245 
246  // Get a constant reference to the mesh.
247  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
248 
249  // Write header to stream
250  {
251  {
252  // TODO: We used to print out the SVN revision here when we did keyword expansions...
253  out_stream << "# For a description of the Tecplot format see the Tecplot User's guide.\n"
254  << "#\n";
255  }
256 
257  out_stream << "Variables=x,y,z";
258 
259  if (solution_names != nullptr)
260  for (const auto & val : *solution_names)
261  {
262 #ifdef LIBMESH_USE_REAL_NUMBERS
263 
264  // Write variable names for real variables
265  out_stream << "," << val;
266 
267 #else
268 
269  // Write variable names for complex variables
270  out_stream << "," << "r_" << val
271  << "," << "i_" << val
272  << "," << "a_" << val;
273 
274 #endif
275  }
276 
277  out_stream << '\n';
278 
279  out_stream << "Zone f=fepoint, n=" << the_mesh.n_nodes() << ", e=" << the_mesh.n_active_sub_elem();
280 
281  // We cannot choose the element type simply based on the mesh
282  // dimension... there might be 1D elements living in a 3D mesh.
283  // So look at the elements which are actually in the Mesh, and
284  // choose either "lineseg", "quadrilateral", or "brick" depending
285  // on if the elements are 1, 2, or 3D.
286 
287  // Write the element type we've determined to the header.
288  out_stream << ", et=";
289 
290  switch (this->elem_dimension())
291  {
292  case 1:
293  out_stream << "lineseg";
294  break;
295  case 2:
296  out_stream << "quadrilateral";
297  break;
298  case 3:
299  out_stream << "brick";
300  break;
301  default:
302  libmesh_error_msg("Unsupported element dimension: " << this->elem_dimension());
303  }
304 
305  // Output the time in the header
306  out_stream << ", t=\"T " << _time << "\"";
307 
308  // Use default mesh color = black
309  out_stream << ", c=black\n";
310 
311  } // finished writing header
312 
313  for (auto i : make_range(the_mesh.n_nodes()))
314  {
315  // Print the point without a newline
316  the_mesh.point(i).write_unformatted(out_stream, false);
317 
318  if ((v != nullptr) && (solution_names != nullptr))
319  {
320  const std::size_t n_vars = solution_names->size();
321 
322 
323  for (std::size_t c=0; c<n_vars; c++)
324  {
325 #ifdef LIBMESH_USE_REAL_NUMBERS
326  // Write real data
327  out_stream << std::setprecision(this->ascii_precision())
328  << (*v)[i*n_vars + c] << " ";
329 
330 #else
331  // Write complex data
332  out_stream << std::setprecision(this->ascii_precision())
333  << (*v)[i*n_vars + c].real() << " "
334  << (*v)[i*n_vars + c].imag() << " "
335  << std::abs((*v)[i*n_vars + c]) << " ";
336 
337 #endif
338  }
339  }
340 
341  // Write a new line after the data for this node
342  out_stream << '\n';
343  }
344 
345  for (const auto & elem : the_mesh.active_element_ptr_range())
346  elem->write_connectivity(out_stream, TECPLOT);
347 }
const MeshBase & mesh() const
Definition: mesh_output.h:259
double _time
Solution time.
Definition: tecplot_io.h:151
unsigned int & ascii_precision()
Return/set the precision to use when writing ASCII files.
Definition: mesh_output.h:269
const unsigned int n_vars
Definition: tecplot_io.C:68
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:57
unsigned elem_dimension()
Determines the logical spatial dimension of the elements in the Mesh.
Definition: tecplot_io.C:204
OStreamProxy out
bool _ascii_append
If true, when writing in ASCII format, open the file in std::ofstream::app mode.
Definition: tecplot_io.h:167
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...
Definition: int_range.h:134

◆ write_binary()

void libMesh::TecplotIO::write_binary ( const std::string &  fname,
const std::vector< Number > *  vec = nullptr,
const std::vector< std::string > *  solution_names = nullptr 
)
private

This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are optionally provided.

This will write a binary file if the tecio.a library was found at compile time, otherwise a warning message will be printed and an ASCII file will be created.

Definition at line 351 of file tecplot_io.C.

References _subdomain_ids, _time, std::abs(), libMesh::as_range(), elem_dimension(), libMesh::err, libMesh::ierr, libMesh::index_range(), libMesh::make_range(), libMesh::MeshOutput< MT >::mesh(), libMesh::MeshOutput< MeshBase >::mesh(), libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_active_sub_elem(), libMesh::MeshBase::n_nodes(), n_vars, libMesh::MeshBase::point(), strand_offset(), libMesh::MeshBase::subdomain_name(), libMesh::TECPLOT, write_ascii(), and zone_title().

Referenced by write(), and write_nodal_data().

354 {
355  //-----------------------------------------------------------
356  // Call the ASCII output function if configure did not detect
357  // the Tecplot binary API
358 #ifndef LIBMESH_HAVE_TECPLOT_API
359 
360  libMesh::err << "WARNING: Tecplot Binary files require the Tecplot API." << std::endl
361  << "Continuing with ASCII output."
362  << std::endl;
363 
364  if (this->mesh().processor_id() == 0)
365  this->write_ascii (fname, vec, solution_names);
366  return;
367 
368 
369 
370  //------------------------------------------------------------
371  // New binary formats, time aware and whatnot
372 #elif defined(LIBMESH_HAVE_TECPLOT_API_112)
373 
374  // Get a constant reference to the mesh.
375  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
376 
377  // Required variables
378  std::string tecplot_variable_names;
379  int
380  ierr = 0,
381  file_type = 0, // full
382  is_double = 0,
383 #ifdef DEBUG
384  tec_debug = 1,
385 #else
386  tec_debug = 0,
387 #endif
388  cell_type = -1,
389  nn_per_elem = -1;
390 
391  switch (this->elem_dimension())
392  {
393  case 1:
394  cell_type = 1; // FELINESEG
395  nn_per_elem = 2;
396  break;
397 
398  case 2:
399  cell_type = 3; // FEQUADRILATERAL
400  nn_per_elem = 4;
401  break;
402 
403  case 3:
404  cell_type = 5; // FEBRICK
405  nn_per_elem = 8;
406  break;
407 
408  default:
409  libmesh_error_msg("Unsupported element dimension: " << this->elem_dimension());
410  }
411 
412  // Build a string containing all the variable names to pass to Tecplot
413  {
414  tecplot_variable_names += "x, y, z";
415 
416  if (solution_names != nullptr)
417  {
418  for (const auto & val : *solution_names)
419  {
420 #ifdef LIBMESH_USE_REAL_NUMBERS
421 
422  tecplot_variable_names += ", ";
423  tecplot_variable_names += val;
424 
425 #else
426 
427  tecplot_variable_names += ", ";
428  tecplot_variable_names += "r_";
429  tecplot_variable_names += val;
430  tecplot_variable_names += ", ";
431  tecplot_variable_names += "i_";
432  tecplot_variable_names += val;
433  tecplot_variable_names += ", ";
434  tecplot_variable_names += "a_";
435  tecplot_variable_names += val;
436 
437 #endif
438  }
439  }
440  }
441 
442  // Instantiate a TecplotMacros interface. In 2D the most nodes per
443  // face should be 4, in 3D it's 8.
444 
445 
446  TecplotMacros tm(the_mesh.n_nodes(),
447 #ifdef LIBMESH_USE_REAL_NUMBERS
448  (3 + ((solution_names == nullptr) ? 0 :
449  cast_int<unsigned int>(solution_names->size()))),
450 #else
451  (3 + 3*((solution_names == nullptr) ? 0 :
452  cast_int<unsigned int>(solution_names->size()))),
453 #endif
454  the_mesh.n_active_sub_elem(),
455  nn_per_elem
456  );
457 
458 
459  // Copy the nodes and data to the TecplotMacros class. Note that we store
460  // everything as a float here since the eye doesn't require a double to
461  // understand what is going on
462  for (auto v : make_range(the_mesh.n_nodes()))
463  {
464  tm.nd(0,v) = static_cast<float>(the_mesh.point(v)(0));
465  tm.nd(1,v) = static_cast<float>(the_mesh.point(v)(1));
466  tm.nd(2,v) = static_cast<float>(the_mesh.point(v)(2));
467 
468  if ((vec != nullptr) &&
469  (solution_names != nullptr))
470  {
471  const std::size_t n_vars = solution_names->size();
472 
473  for (std::size_t c=0; c<n_vars; c++)
474  {
475 #ifdef LIBMESH_USE_REAL_NUMBERS
476 
477  tm.nd((3+c),v) = static_cast<float>((*vec)[v*n_vars + c]);
478 #else
479  tm.nd((3+3*c),v) = static_cast<float>((*vec)[v*n_vars + c].real());
480  tm.nd((3+3*c+1),v) = static_cast<float>((*vec)[v*n_vars + c].imag());
481  tm.nd((3+3*c+2),v) = static_cast<float>(std::abs((*vec)[v*n_vars + c]));
482 #endif
483  }
484  }
485  }
486 
487 
488  // Initialize the file
489  ierr = TECINI112 (nullptr,
490  const_cast<char *>(tecplot_variable_names.c_str()),
491  const_cast<char *>(fname.c_str()),
492  const_cast<char *>("."),
493  &file_type,
494  &tec_debug,
495  &is_double);
496 
497  if (ierr)
498  libmesh_file_error(fname);
499 
500  // A zone for each subdomain
501  bool firstzone=true;
502  for (const auto & sbd_id : _subdomain_ids)
503  {
504  // Copy the connectivity for this subdomain
505  {
506  unsigned int n_subcells_in_subdomain=0;
507 
508  for (const auto & elem :
509  as_range(the_mesh.active_subdomain_elements_begin(sbd_id),
510  the_mesh.active_subdomain_elements_end(sbd_id)))
511  n_subcells_in_subdomain += elem->n_sub_elem();
512 
513  // update the connectivity array to include only the elements in this subdomain
514  tm.set_n_cells (n_subcells_in_subdomain);
515 
516  unsigned int te = 0;
517 
518  for (const auto & elem :
519  as_range(the_mesh.active_subdomain_elements_begin(sbd_id),
520  the_mesh.active_subdomain_elements_end(sbd_id)))
521  {
522  std::vector<dof_id_type> conn;
523  for (auto se : make_range(elem->n_sub_elem()))
524  {
525  elem->connectivity(se, TECPLOT, conn);
526 
527  for (auto node : index_range(conn))
528  tm.cd(node,te) = conn[node];
529 
530  te++;
531  }
532  }
533  }
534 
535 
536  // Ready to call the Tecplot API for this subdomain
537  {
538  int
539  num_nodes = static_cast<int>(the_mesh.n_nodes()),
540  num_cells = static_cast<int>(tm.n_cells),
541  num_faces = 0,
542  i_cell_max = 0,
543  j_cell_max = 0,
544  k_cell_max = 0,
545  strand_id = std::max(sbd_id, static_cast<subdomain_id_type>(1)) + this->strand_offset(),
546  parent_zone = 0,
547  is_block = 1,
548  num_face_connect = 0,
549  face_neighbor_mode = 0,
550  tot_num_face_nodes = 0,
551  num_connect_boundary_faces = 0,
552  tot_num_boundary_connect = 0,
553  share_connect_from_zone=0;
554 
555  std::vector<int>
556  passive_var_list (tm.n_vars, 0),
557  share_var_from_zone (tm.n_vars, 1); // We only write data for the first zone, all other
558  // zones will share from this one.
559 
560  // get the subdomain name from libMesh, if there is one.
561  std::string subdomain_name = the_mesh.subdomain_name(sbd_id);
562  std::ostringstream zone_name;
563  zone_name << this->zone_title();
564 
565  // We will title this
566  // "{zone_title()}_{subdomain_name}", or
567  // "{zone_title()}_{subdomain_id}", or
568  // "{zone_title()}"
569  if (subdomain_name.size())
570  {
571  zone_name << "_";
572  zone_name << subdomain_name;
573  }
574  else if (_subdomain_ids.size() > 1)
575  {
576  zone_name << "_";
577  zone_name << sbd_id;
578  }
579 
580  ierr = TECZNE112 (const_cast<char *>(zone_name.str().c_str()),
581  &cell_type,
582  &num_nodes,
583  &num_cells,
584  &num_faces,
585  &i_cell_max,
586  &j_cell_max,
587  &k_cell_max,
588  &_time,
589  &strand_id,
590  &parent_zone,
591  &is_block,
592  &num_face_connect,
593  &face_neighbor_mode,
594  &tot_num_face_nodes,
595  &num_connect_boundary_faces,
596  &tot_num_boundary_connect,
597  passive_var_list.data(),
598  nullptr, // = all are node centered
599  (firstzone) ? nullptr : share_var_from_zone.data(),
600  &share_connect_from_zone);
601 
602  if (ierr)
603  libmesh_file_error(fname);
604 
605  // Write *all* the data for the first zone, then share it with the others
606  if (firstzone)
607  {
608  int total = cast_int<int>
609 #ifdef LIBMESH_USE_REAL_NUMBERS
610  ((3 + ((solution_names == nullptr) ? 0 : solution_names->size()))*num_nodes);
611 #else
612  ((3 + 3*((solution_names == nullptr) ? 0 : solution_names->size()))*num_nodes);
613 #endif
614 
615 
616  ierr = TECDAT112 (&total,
617  tm.nodalData.data(),
618  &is_double);
619 
620  if (ierr)
621  libmesh_file_error(fname);
622  }
623 
624  // Write the connectivity
625  ierr = TECNOD112 (tm.connData.data());
626 
627  if (ierr)
628  libmesh_file_error(fname);
629  }
630 
631  firstzone = false;
632  }
633 
634  // Done, close the file.
635  ierr = TECEND112 ();
636 
637  if (ierr)
638  libmesh_file_error(fname);
639 
640 
641 
642 
643  //------------------------------------------------------------
644  // Legacy binary format
645 #else
646 
647  // Get a constant reference to the mesh.
648  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
649 
650  // Tecplot binary output only good for dim=2,3
651  if (the_mesh.mesh_dimension() == 1)
652  {
653  this->write_ascii (fname, vec, solution_names);
654 
655  return;
656  }
657 
658  // Required variables
659  std::string tecplot_variable_names;
660  int is_double = 0,
661  tec_debug = 0,
662  cell_type = ((the_mesh.mesh_dimension()==2) ? (1) : (3));
663 
664  // Build a string containing all the variable names to pass to Tecplot
665  {
666  tecplot_variable_names += "x, y, z";
667 
668  if (solution_names != nullptr)
669  {
670  for (const auto & val : *solution_names)
671  {
672 #ifdef LIBMESH_USE_REAL_NUMBERS
673 
674  tecplot_variable_names += ", ";
675  tecplot_variable_names += val;
676 
677 #else
678 
679  tecplot_variable_names += ", ";
680  tecplot_variable_names += "r_";
681  tecplot_variable_names += val;
682  tecplot_variable_names += ", ";
683  tecplot_variable_names += "i_";
684  tecplot_variable_names += val;
685  tecplot_variable_names += ", ";
686  tecplot_variable_names += "a_";
687  tecplot_variable_names += val;
688 
689 #endif
690  }
691  }
692  }
693 
694  // Instantiate a TecplotMacros interface. In 2D the most nodes per
695  // face should be 4, in 3D it's 8.
696 
697 
698  TecplotMacros tm(cast_int<unsigned int>(the_mesh.n_nodes()),
699  cast_int<unsigned int>
700 #ifdef LIBMESH_USE_REAL_NUMBERS
701  (3 + ((solution_names == nullptr) ? 0 : solution_names->size())),
702 #else
703  (3 + 3*((solution_names == nullptr) ? 0 : solution_names->size())),
704 #endif
705  cast_int<unsigned int>
706  (the_mesh.n_active_sub_elem()),
707  ((the_mesh.mesh_dimension() == 2) ? 4 : 8)
708  );
709 
710 
711  // Copy the nodes and data to the TecplotMacros class. Note that we store
712  // everything as a float here since the eye doesn't require a double to
713  // understand what is going on
714  for (auto v : make_range(the_mesh.n_nodes()))
715  {
716  tm.nd(0,v) = static_cast<float>(the_mesh.point(v)(0));
717  tm.nd(1,v) = static_cast<float>(the_mesh.point(v)(1));
718  tm.nd(2,v) = static_cast<float>(the_mesh.point(v)(2));
719 
720  if ((vec != nullptr) &&
721  (solution_names != nullptr))
722  {
723  const std::size_t n_vars = solution_names->size();
724 
725  for (std::size_t c=0; c<n_vars; c++)
726  {
727 #ifdef LIBMESH_USE_REAL_NUMBERS
728 
729  tm.nd((3+c),v) = static_cast<float>((*vec)[v*n_vars + c]);
730 #else
731  tm.nd((3+3*c),v) = static_cast<float>((*vec)[v*n_vars + c].real());
732  tm.nd((3+3*c+1),v) = static_cast<float>((*vec)[v*n_vars + c].imag());
733  tm.nd((3+3*c+2),v) = static_cast<float>(std::abs((*vec)[v*n_vars + c]));
734 #endif
735  }
736  }
737  }
738 
739 
740  // Copy the connectivity
741  {
742  unsigned int te = 0;
743 
744  for (const auto & elem : the_mesh.active_element_ptr_range())
745  {
746  std::vector<dof_id_type> conn;
747  for (auto se : make_range(elem->n_sub_elem()))
748  {
749  elem->connectivity(se, TECPLOT, conn);
750 
751  for (auto node : index_range(conn))
752  tm.cd(node,te) = conn[node];
753 
754  te++;
755  }
756  }
757  }
758 
759 
760  // Ready to call the Tecplot API
761  {
762  int ierr = 0,
763  num_nodes = static_cast<int>(the_mesh.n_nodes()),
764  num_cells = static_cast<int>(the_mesh.n_active_sub_elem());
765 
766 
767  ierr = TECINI (nullptr,
768  (char *) tecplot_variable_names.c_str(),
769  (char *) fname.c_str(),
770  (char *) ".",
771  &tec_debug,
772  &is_double);
773 
774  if (ierr)
775  libmesh_file_error(fname);
776 
777 
778  ierr = TECZNE (nullptr,
779  &num_nodes,
780  &num_cells,
781  &cell_type,
782  (char *) "FEBLOCK",
783  nullptr);
784 
785  if (ierr)
786  libmesh_file_error(fname);
787 
788 
789  int total =
790 #ifdef LIBMESH_USE_REAL_NUMBERS
791  ((3 + ((solution_names == nullptr) ? 0 : solution_names->size()))*num_nodes);
792 #else
793  ((3 + 3*((solution_names == nullptr) ? 0 : solution_names->size()))*num_nodes);
794 #endif
795 
796 
797  ierr = TECDAT (&total,
798  tm.nodalData.data(),
799  &is_double);
800 
801  if (ierr)
802  libmesh_file_error(fname);
803 
804  ierr = TECNOD (tm.connData.data());
805 
806  if (ierr)
807  libmesh_file_error(fname);
808 
809  ierr = TECEND ();
810 
811  if (ierr)
812  libmesh_file_error(fname);
813  }
814 
815 #endif
816 }
OStreamProxy err
const MeshBase & mesh() const
Definition: mesh_output.h:259
int & strand_offset()
Strand offset for this file.
Definition: tecplot_io.C:155
double _time
Solution time.
Definition: tecplot_io.h:151
const unsigned int n_vars
Definition: tecplot_io.C:68
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:57
std::set< subdomain_id_type > _subdomain_ids
The subdomains in the mesh.
Definition: tecplot_io.h:172
void write_ascii(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: tecplot_io.C:232
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
unsigned elem_dimension()
Determines the logical spatial dimension of the elements in the Mesh.
Definition: tecplot_io.C:204
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...
Definition: int_range.h:134
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:111
std::string & zone_title()
The zone title to write.
Definition: tecplot_io.C:162

◆ write_discontinuous_equation_systems()

void libMesh::MeshOutput< MeshBase >::write_discontinuous_equation_systems ( const std::string &  fname,
const EquationSystems es,
const std::set< std::string > *  system_names = nullptr 
)
virtualinherited

This method implements writing a mesh with discontinuous data to a specified file where the data is taken from the EquationSystems object.

Definition at line 89 of file mesh_output.C.

References libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::EquationSystems::build_variable_names(), libMesh::EquationSystems::get_mesh(), libMesh::libmesh_assert(), and libMesh::out.

Referenced by libMesh::ExodusII_IO::write_timestep_discontinuous().

92 {
93  LOG_SCOPE("write_discontinuous_equation_systems()", "MeshOutput");
94 
95  // We may need to gather and/or renumber a DistributedMesh to output
96  // it, making that const qualifier in our constructor a dirty lie
97  MT & my_mesh = const_cast<MT &>(*_obj);
98 
99  // If we're asked to write data that's associated with a different
100  // mesh, output files full of garbage are the result.
101  libmesh_assert_equal_to(&es.get_mesh(), _obj);
102 
103  // A non-renumbered mesh may not have a contiguous numbering, and
104  // that needs to be fixed before we can build a solution vector.
105  if (my_mesh.max_elem_id() != my_mesh.n_elem() ||
106  my_mesh.max_node_id() != my_mesh.n_nodes())
107  {
108  // If we were allowed to renumber then we should have already
109  // been properly renumbered...
110  libmesh_assert(!my_mesh.allow_renumbering());
111 
112  libmesh_do_once(libMesh::out <<
113  "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
114  << std::endl;);
115 
116  my_mesh.allow_renumbering(true);
117 
118  my_mesh.renumber_nodes_and_elements();
119 
120  // Not sure what good going back to false will do here, the
121  // renumbering horses have already left the barn...
122  my_mesh.allow_renumbering(false);
123  }
124 
125  MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
126 
127  // Build the list of variable names that will be written.
128  std::vector<std::string> names;
129  es.build_variable_names (names, nullptr, system_names);
130 
131  if (!_is_parallel_format)
132  {
133  // Build the nodal solution values & get the variable
134  // names from the EquationSystems object
135  std::vector<Number> soln;
136  es.build_discontinuous_solution_vector (soln, system_names,
137  nullptr, false, /* defaults */
138  this->get_add_sides());
139 
140  this->write_nodal_data_discontinuous (fname, soln, names);
141  }
142  else // _is_parallel_format
143  {
144  libmesh_not_implemented();
145  }
146 }
virtual void write_nodal_data_discontinuous(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
This method implements writing a mesh with discontinuous data to a specified file where the nodal dat...
Definition: mesh_output.h:118
const MeshBase *const _obj
A pointer to a constant object.
Definition: mesh_output.h:202
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
Definition: mesh_output.h:184
libmesh_assert(ctx)
OStreamProxy out
const bool _serial_only_needed_on_proc_0
Flag specifying whether this format can be written by only serializing the mesh to processor zero...
Definition: mesh_output.h:193

◆ write_equation_systems()

void libMesh::MeshOutput< MeshBase >::write_equation_systems ( const std::string &  fname,
const EquationSystems es,
const std::set< std::string > *  system_names = nullptr 
)
virtualinherited

This method implements writing a mesh with data to a specified file where the data is taken from the EquationSystems object.

Reimplemented in libMesh::NameBasedIO.

Definition at line 31 of file mesh_output.C.

References libMesh::EquationSystems::build_solution_vector(), libMesh::EquationSystems::build_variable_names(), libMesh::EquationSystems::get_mesh(), libMesh::libmesh_assert(), and libMesh::out.

Referenced by libMesh::Nemesis_IO::write_timestep(), and libMesh::ExodusII_IO::write_timestep().

34 {
35  LOG_SCOPE("write_equation_systems()", "MeshOutput");
36 
37  // We may need to gather and/or renumber a DistributedMesh to output
38  // it, making that const qualifier in our constructor a dirty lie
39  MT & my_mesh = const_cast<MT &>(*_obj);
40 
41  // If we're asked to write data that's associated with a different
42  // mesh, output files full of garbage are the result.
43  libmesh_assert_equal_to(&es.get_mesh(), _obj);
44 
45  // A non-parallel format, non-renumbered mesh may not have a contiguous
46  // numbering, and that needs to be fixed before we can build a solution vector.
47  if (!_is_parallel_format &&
48  (my_mesh.max_elem_id() != my_mesh.n_elem() ||
49  my_mesh.max_node_id() != my_mesh.n_nodes()))
50  {
51  // If we were allowed to renumber then we should have already
52  // been properly renumbered...
53  libmesh_assert(!my_mesh.allow_renumbering());
54 
55  libmesh_do_once(libMesh::out <<
56  "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
57  << std::endl;);
58 
59  my_mesh.allow_renumbering(true);
60 
61  my_mesh.renumber_nodes_and_elements();
62 
63  // Not sure what good going back to false will do here, the
64  // renumbering horses have already left the barn...
65  my_mesh.allow_renumbering(false);
66  }
67 
69  {
70  MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
71 
72  // Build the list of variable names that will be written.
73  std::vector<std::string> names;
74  es.build_variable_names (names, nullptr, system_names);
75 
76  // Build the nodal solution values & get the variable
77  // names from the EquationSystems object
78  std::vector<Number> soln;
79  es.build_solution_vector (soln, system_names,
80  this->get_add_sides());
81 
82  this->write_nodal_data (fname, soln, names);
83  }
84  else // _is_parallel_format
85  this->write_nodal_data (fname, es, system_names);
86 }
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: mesh_output.h:109
const MeshBase *const _obj
A pointer to a constant object.
Definition: mesh_output.h:202
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
Definition: mesh_output.h:184
libmesh_assert(ctx)
OStreamProxy out
const bool _serial_only_needed_on_proc_0
Flag specifying whether this format can be written by only serializing the mesh to processor zero...
Definition: mesh_output.h:193

◆ write_nodal_data() [1/3]

void libMesh::TecplotIO::write_nodal_data ( const std::string &  fname,
const std::vector< Number > &  soln,
const std::vector< std::string > &  names 
)
overridevirtual

This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are provided.

Reimplemented from libMesh::MeshOutput< MeshBase >.

Definition at line 187 of file tecplot_io.C.

References binary(), libMesh::MeshOutput< MeshBase >::mesh(), write_ascii(), and write_binary().

Referenced by libMesh::NameBasedIO::write_nodal_data().

190 {
191  LOG_SCOPE("write_nodal_data()", "TecplotIO");
192 
193  if (this->mesh().processor_id() == 0)
194  {
195  if (this->binary())
196  this->write_binary (fname, &soln, &names);
197  else
198  this->write_ascii (fname, &soln, &names);
199  }
200 }
const MeshBase & mesh() const
Definition: mesh_output.h:259
bool & binary()
Flag indicating whether or not to write a binary file (if the tecio.a library was found by configure)...
Definition: tecplot_io.C:141
void write_ascii(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: tecplot_io.C:232
void write_binary(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: tecplot_io.C:351

◆ write_nodal_data() [2/3]

void libMesh::MeshOutput< MeshBase >::write_nodal_data ( const std::string &  fname,
const NumericVector< Number > &  parallel_soln,
const std::vector< std::string > &  names 
)
virtualinherited

This method may be overridden by "parallel" output formats for writing nodal data.

Instead of getting a localized copy of the nodal solution vector, it is passed a NumericVector of type=PARALLEL which is in node-major order i.e. (u0,v0,w0, u1,v1,w1, u2,v2,w2, u3,v3,w3, ...) and contains n_nodes*n_vars total entries. Then, it is up to the individual I/O class to extract the required solution values from this vector and write them in parallel.

If not implemented, localizes the parallel vector into a std::vector and calls the other version of this function.

Reimplemented in libMesh::Nemesis_IO.

Definition at line 149 of file mesh_output.C.

References libMesh::NumericVector< T >::localize().

152 {
153  // This is the fallback implementation for parallel I/O formats that
154  // do not yet implement proper writing in parallel, and instead rely
155  // on the full solution vector being available on all processors.
156  std::vector<Number> soln;
157  parallel_soln.localize(soln);
158  this->write_nodal_data(fname, soln, names);
159 }
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: mesh_output.h:109
virtual void localize(std::vector< T > &v_local) const =0
Creates a copy of the global vector in the local vector v_local.

◆ write_nodal_data() [3/3]

void libMesh::MeshOutput< MeshBase >::write_nodal_data ( const std::string &  fname,
const EquationSystems es,
const std::set< std::string > *  system_names 
)
virtualinherited

This method should be overridden by "parallel" output formats for writing nodal data.

Instead of getting a localized copy of the nodal solution vector, it directly uses EquationSystems current_local_solution vectors to look up nodal values.

If not implemented, reorders the solutions into a nodal-only NumericVector and calls the above version of this function.

Reimplemented in libMesh::Nemesis_IO.

Definition at line 162 of file mesh_output.C.

References libMesh::EquationSystems::build_parallel_solution_vector(), and libMesh::EquationSystems::build_variable_names().

165 {
166  std::vector<std::string> names;
167  es.build_variable_names (names, nullptr, system_names);
168 
169  std::unique_ptr<NumericVector<Number>> parallel_soln =
170  es.build_parallel_solution_vector(system_names);
171 
172  this->write_nodal_data (fname, *parallel_soln, names);
173 }
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: mesh_output.h:109

◆ write_nodal_data_discontinuous()

virtual void libMesh::MeshOutput< MeshBase >::write_nodal_data_discontinuous ( const std::string &  ,
const std::vector< Number > &  ,
const std::vector< std::string > &   
)
inlinevirtualinherited

This method implements writing a mesh with discontinuous data to a specified file where the nodal data and variables names are provided.

Reimplemented in libMesh::ExodusII_IO.

Definition at line 118 of file mesh_output.h.

121  { libmesh_not_implemented(); }

◆ zone_title()

std::string & libMesh::TecplotIO::zone_title ( )

The zone title to write.

Definition at line 162 of file tecplot_io.C.

References _zone_title.

Referenced by write_binary().

163 {
164  return _zone_title;
165 }
std::string _zone_title
The zone title to write.
Definition: tecplot_io.h:161

Member Data Documentation

◆ _ascii_append

bool libMesh::TecplotIO::_ascii_append
private

If true, when writing in ASCII format, open the file in std::ofstream::app mode.

Definition at line 167 of file tecplot_io.h.

Referenced by ascii_append(), and write_ascii().

◆ _binary

bool libMesh::TecplotIO::_binary
private

Flag to write binary data.

Definition at line 146 of file tecplot_io.h.

Referenced by binary().

◆ _is_parallel_format

const bool libMesh::MeshOutput< MeshBase >::_is_parallel_format
protectedinherited

Flag specifying whether this format is parallel-capable.

If this is false (default) I/O is only permitted when the mesh has been serialized.

Definition at line 184 of file mesh_output.h.

Referenced by libMesh::FroIO::write(), libMesh::PostscriptIO::write(), and libMesh::EnsightIO::write().

◆ _serial_only_needed_on_proc_0

const bool libMesh::MeshOutput< MeshBase >::_serial_only_needed_on_proc_0
protectedinherited

Flag specifying whether this format can be written by only serializing the mesh to processor zero.

If this is false (default) the mesh will be serialized to all processors

Definition at line 193 of file mesh_output.h.

◆ _strand_offset

int libMesh::TecplotIO::_strand_offset
private

Offset for Tecplot's STRANDID.

Definition at line 156 of file tecplot_io.h.

Referenced by strand_offset().

◆ _subdomain_ids

std::set<subdomain_id_type> libMesh::TecplotIO::_subdomain_ids
private

The subdomains in the mesh.

Definition at line 172 of file tecplot_io.h.

Referenced by TecplotIO(), and write_binary().

◆ _time

double libMesh::TecplotIO::_time
private

Solution time.

Definition at line 151 of file tecplot_io.h.

Referenced by time(), write_ascii(), and write_binary().

◆ _zone_title

std::string libMesh::TecplotIO::_zone_title
private

The zone title to write.

Definition at line 161 of file tecplot_io.h.

Referenced by zone_title().


The documentation for this class was generated from the following files: