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
 

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...
 
const MeshBase *const _obj
 A pointer to a constant object. More...
 
unsigned int _ascii_precision
 Precision to use when writing ASCII files. 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 122 of file tecplot_io.C.

125  :
126  MeshOutput<MeshBase> (mesh_in),
127  _binary (binary_in),
128  _time (time_in),
129  _strand_offset (strand_offset_in),
130  _zone_title ("zone"),
131  _ascii_append(false)
132 {
133  // Gather a list of subdomain ids in the mesh.
134  // We must do this now, while we have every
135  // processor's attention
136  // (some of the write methods only execute on processor 0).
137  mesh_in.subdomain_ids (_subdomain_ids);
138 }

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

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 169 of file tecplot_io.C.

170 {
171  return _ascii_append;
172 }

References _ascii_append.

◆ 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 257 of file mesh_output.h.

258 {
259  return _ascii_precision;
260 }

◆ 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 142 of file tecplot_io.C.

143 {
144  return _binary;
145 }

References _binary.

Referenced by write(), and write_nodal_data().

◆ 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 205 of file tecplot_io.C.

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

References libMesh::MeshBase::active_element_ptr_range(), and libMesh::MeshOutput< MT >::mesh().

Referenced by write_ascii(), and write_binary().

◆ mesh()

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

Definition at line 247 of file mesh_output.h.

248 {
250  return *_obj;
251 }

◆ 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 156 of file tecplot_io.C.

157 {
158  return _strand_offset;
159 }

References _strand_offset.

Referenced by write_binary().

◆ time()

double & libMesh::TecplotIO::time ( )

Solution time for transient data.

Written to newer binary formats that are time-aware.

Definition at line 149 of file tecplot_io.C.

150 {
151  return _time;
152 }

References _time.

◆ 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 175 of file tecplot_io.C.

176 {
177  if (this->mesh().processor_id() == 0)
178  {
179  if (this->binary())
180  this->write_binary (fname);
181  else
182  this->write_ascii (fname);
183  }
184 }

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

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

◆ 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 233 of file tecplot_io.C.

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

References _ascii_append, _time, std::abs(), libMesh::MeshBase::active_element_ptr_range(), libMesh::MeshOutput< MeshBase >::ascii_precision(), elem_dimension(), libMesh::MeshOutput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::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().

◆ 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 352 of file tecplot_io.C.

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

References _subdomain_ids, _time, std::abs(), libMesh::MeshBase::active_element_ptr_range(), libMesh::MeshBase::active_subdomain_elements_begin(), libMesh::MeshBase::active_subdomain_elements_end(), libMesh::as_range(), elem_dimension(), libMesh::err, libMesh::ierr, std::imag(), libMesh::index_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(), std::real(), strand_offset(), libMesh::MeshBase::subdomain_name(), libMesh::TECPLOT, write_ascii(), and zone_title().

Referenced by write(), and write_nodal_data().

◆ 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 87 of file mesh_output.C.

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

◆ 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.

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-renumbered mesh may not have a contiguous numbering, and
46  // that needs to be fixed before we can build a solution vector.
47  if (my_mesh.max_elem_id() != my_mesh.n_elem() ||
48  my_mesh.max_node_id() != my_mesh.n_nodes())
49  {
50  // If we were allowed to renumber then we should have already
51  // been properly renumbered...
52  libmesh_assert(!my_mesh.allow_renumbering());
53 
54  libmesh_do_once(libMesh::out <<
55  "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
56  << std::endl;);
57 
58  my_mesh.allow_renumbering(true);
59 
60  my_mesh.renumber_nodes_and_elements();
61 
62  // Not sure what good going back to false will do here, the
63  // renumbering horses have already left the barn...
64  my_mesh.allow_renumbering(false);
65  }
66 
68  {
69  MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
70 
71  // Build the list of variable names that will be written.
72  std::vector<std::string> names;
73  es.build_variable_names (names, nullptr, system_names);
74 
75  // Build the nodal solution values & get the variable
76  // names from the EquationSystems object
77  std::vector<Number> soln;
78  es.build_solution_vector (soln, system_names);
79 
80  this->write_nodal_data (fname, soln, names);
81  }
82  else // _is_parallel_format
83  this->write_nodal_data (fname, es, system_names);
84 }

◆ write_nodal_data() [1/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 158 of file mesh_output.C.

161 {
162  std::vector<std::string> names;
163  es.build_variable_names (names, nullptr, system_names);
164 
165  std::unique_ptr<NumericVector<Number>> parallel_soln =
166  es.build_parallel_solution_vector(system_names);
167 
168  this->write_nodal_data (fname, *parallel_soln, names);
169 }

◆ 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 145 of file mesh_output.C.

148 {
149  // This is the fallback implementation for parallel I/O formats that
150  // do not yet implement proper writing in parallel, and instead rely
151  // on the full solution vector being available on all processors.
152  std::vector<Number> soln;
153  parallel_soln.localize(soln);
154  this->write_nodal_data(fname, soln, names);
155 }

◆ write_nodal_data() [3/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 188 of file tecplot_io.C.

191 {
192  LOG_SCOPE("write_nodal_data()", "TecplotIO");
193 
194  if (this->mesh().processor_id() == 0)
195  {
196  if (this->binary())
197  this->write_binary (fname, &soln, &names);
198  else
199  this->write_ascii (fname, &soln, &names);
200  }
201 }

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

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

◆ 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 114 of file mesh_output.h.

117  { libmesh_not_implemented(); }

◆ zone_title()

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

The zone title to write.

Definition at line 163 of file tecplot_io.C.

164 {
165  return _zone_title;
166 }

References _zone_title.

Referenced by write_binary().

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().

◆ _ascii_precision

unsigned int libMesh::MeshOutput< MeshBase >::_ascii_precision
privateinherited

Precision to use when writing ASCII files.

Definition at line 195 of file mesh_output.h.

◆ _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 172 of file mesh_output.h.

◆ _obj

const MeshBase * const libMesh::MeshOutput< MeshBase >::_obj
privateinherited

A pointer to a constant object.

This allows us to write the object to file.

Definition at line 190 of file mesh_output.h.

◆ _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 181 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:
n_vars
const unsigned int n_vars
Definition: tecplot_io.C:69
libMesh::MeshOutput< MeshBase >::_serial_only_needed_on_proc_0
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:181
libMesh::TecplotIO::write_binary
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:352
libMesh::TecplotIO::_binary
bool _binary
Flag to write binary data.
Definition: tecplot_io.h:146
libMesh::TecplotIO::_subdomain_ids
std::set< subdomain_id_type > _subdomain_ids
The subdomains in the mesh.
Definition: tecplot_io.h:172
libMesh::TecplotIO::_time
double _time
Solution time.
Definition: tecplot_io.h:151
libMesh::TecplotIO::binary
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:142
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh::TecplotIO::zone_title
std::string & zone_title()
The zone title to write.
Definition: tecplot_io.C:163
libMesh::TecplotIO::strand_offset
int & strand_offset()
Strand offset for this file.
Definition: tecplot_io.C:156
libMesh::ierr
ierr
Definition: petsc_dm_wrapper.C:72
libMesh::MeshOutput< MeshBase >::ascii_precision
unsigned int & ascii_precision()
Return/set the precision to use when writing ASCII files.
Definition: mesh_output.h:257
libMesh::TecplotIO::_zone_title
std::string _zone_title
The zone title to write.
Definition: tecplot_io.h:161
libMesh::libmesh_assert
libmesh_assert(ctx)
std::abs
MetaPhysicL::DualNumber< T, D > abs(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::NumericVector::localize
virtual void localize(std::vector< T > &v_local) const =0
Creates a copy of the global vector in the local vector v_local.
libMesh::MeshOutput< MeshBase >::_is_parallel_format
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
Definition: mesh_output.h:172
libMesh::as_range
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
libMesh::TecplotIO::write_ascii
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:233
libMesh::TecplotIO::_ascii_append
bool _ascii_append
If true, when writing in ASCII format, open the file in std::ofstream::app mode.
Definition: tecplot_io.h:167
libMesh::MeshOutput< MeshBase >::write_nodal_data
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:105
libMesh::MeshOutput::mesh
const MT & mesh() const
Definition: mesh_output.h:247
libMesh::MeshOutput< MeshBase >::write_nodal_data_discontinuous
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:114
libMesh::MeshOutput< MeshBase >::_obj
const MeshBase *const _obj
A pointer to a constant object.
Definition: mesh_output.h:190
libMesh::err
OStreamProxy err
libMesh::TecplotIO::_strand_offset
int _strand_offset
Offset for Tecplot's STRANDID.
Definition: tecplot_io.h:156
libMesh::out
OStreamProxy out
std::imag
boost::multiprecision::float128 imag(const boost::multiprecision::float128)
Definition: float128_shims.h:83
libMesh::TECPLOT
Definition: enum_io_package.h:39
libMesh::MeshOutput< MeshBase >::_ascii_precision
unsigned int _ascii_precision
Precision to use when writing ASCII files.
Definition: mesh_output.h:195
libMesh::TecplotIO::elem_dimension
unsigned elem_dimension()
Determines the logical spatial dimension of the elements in the Mesh.
Definition: tecplot_io.C:205
std::real
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
Definition: float128_shims.h:77