libMesh::TecplotIO Class Reference

#include <tecplot_io.h>

Inheritance diagram for libMesh::TecplotIO:

Public Member Functions

 TecplotIO (const MeshBase &, const bool binary=false, const double time=0., const int strand_offset=0)
 
virtual void write (const std::string &) override
 
virtual void write_nodal_data (const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
 
bool & binary ()
 
double & time ()
 
int & strand_offset ()
 
std::string & zone_title ()
 
bool & ascii_append ()
 
virtual void write_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
 
virtual void write_discontinuous_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
 
virtual void write_nodal_data (const std::string &, const NumericVector< Number > &, const std::vector< std::string > &)
 
virtual void write_nodal_data_discontinuous (const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
 
unsigned int & ascii_precision ()
 

Protected Member Functions

const MeshBasemesh () const
 

Protected Attributes

const bool _is_parallel_format
 
const bool _serial_only_needed_on_proc_0
 

Private Member Functions

void write_ascii (const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
 
void write_binary (const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
 
unsigned elem_dimension ()
 

Private Attributes

bool _binary
 
double _time
 
int _strand_offset
 
std::string _zone_title
 
bool _ascii_append
 
std::set< subdomain_id_type_subdomain_ids
 

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.

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

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 }
std::set< subdomain_id_type > _subdomain_ids
Definition: tecplot_io.h:172
std::string _zone_title
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 169 of file tecplot_io.C.

References _ascii_append.

170 {
171  return _ascii_append;
172 }

◆ 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>::digits10 + 2, which should be enough to write out to ASCII and get the exact same Real back when reading in.

Definition at line 244 of file mesh_output.h.

Referenced by write_ascii(), libMesh::GMVIO::write_ascii_new_impl(), and libMesh::GMVIO::write_ascii_old_impl().

245 {
246  return _ascii_precision;
247 }

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

References _binary.

Referenced by write(), and write_nodal_data().

143 {
144  return _binary;
145 }

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

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

Referenced by write_ascii(), and write_binary().

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 }
const MT & mesh() const
Definition: mesh_output.h:234

◆ mesh()

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

Definition at line 234 of file mesh_output.h.

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

235 {
236  libmesh_assert(_obj);
237  return *_obj;
238 }
const MeshBase *const _obj
Definition: mesh_output.h:177

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

References _strand_offset.

Referenced by write_binary().

157 {
158  return _strand_offset;
159 }

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

References _time.

150 {
151  return _time;
152 }

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

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

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

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 }
const MeshBase & mesh() const
Definition: mesh_output.h:234
void write_ascii(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
Definition: tecplot_io.C:233
void write_binary(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
Definition: tecplot_io.C:352

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

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

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 (std::size_t n=0; n<solution_names->size(); n++)
262  {
263 #ifdef LIBMESH_USE_REAL_NUMBERS
264 
265  // Write variable names for real variables
266  out_stream << "," << (*solution_names)[n];
267 
268 #else
269 
270  // Write variable names for complex variables
271  out_stream << "," << "r_" << (*solution_names)[n]
272  << "," << "i_" << (*solution_names)[n]
273  << "," << "a_" << (*solution_names)[n];
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 (unsigned int i=0; i<the_mesh.n_nodes(); i++)
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 }
const MeshBase & mesh() const
Definition: mesh_output.h:234
double abs(double a)
unsigned int & ascii_precision()
Definition: mesh_output.h:244
const unsigned int n_vars
Definition: tecplot_io.C:69
unsigned elem_dimension()
Definition: tecplot_io.C:205
OStreamProxy out(std::cout)

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

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, ierr, std::max(), 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::Quality::name(), libMesh::MeshBase::point(), strand_offset(), libMesh::MeshBase::subdomain_name(), libMesh::TECPLOT, write_ascii(), and zone_title().

Referenced by write(), and write_nodal_data().

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 (std::size_t name=0; name<solution_names->size(); name++)
420  {
421 #ifdef LIBMESH_USE_REAL_NUMBERS
422 
423  tecplot_variable_names += ", ";
424  tecplot_variable_names += (*solution_names)[name];
425 
426 #else
427 
428  tecplot_variable_names += ", ";
429  tecplot_variable_names += "r_";
430  tecplot_variable_names += (*solution_names)[name];
431  tecplot_variable_names += ", ";
432  tecplot_variable_names += "i_";
433  tecplot_variable_names += (*solution_names)[name];
434  tecplot_variable_names += ", ";
435  tecplot_variable_names += "a_";
436  tecplot_variable_names += (*solution_names)[name];
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 (unsigned int v=0; v<the_mesh.n_nodes(); v++)
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 (unsigned int se=0; se<elem->n_sub_elem(); se++)
525  {
526  elem->connectivity(se, TECPLOT, conn);
527 
528  for (std::size_t node=0; node<conn.size(); node++)
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 (std::size_t name=0; name<solution_names->size(); name++)
672  {
673 #ifdef LIBMESH_USE_REAL_NUMBERS
674 
675  tecplot_variable_names += ", ";
676  tecplot_variable_names += (*solution_names)[name];
677 
678 #else
679 
680  tecplot_variable_names += ", ";
681  tecplot_variable_names += "r_";
682  tecplot_variable_names += (*solution_names)[name];
683  tecplot_variable_names += ", ";
684  tecplot_variable_names += "i_";
685  tecplot_variable_names += (*solution_names)[name];
686  tecplot_variable_names += ", ";
687  tecplot_variable_names += "a_";
688  tecplot_variable_names += (*solution_names)[name];
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 (unsigned int v=0; v<the_mesh.n_nodes(); v++)
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 (unsigned int se=0; se<elem->n_sub_elem(); se++)
749  {
750  elem->connectivity(se, TECPLOT, conn);
751 
752  for (std::size_t node=0; node<conn.size(); node++)
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 }
std::string name(const ElemQuality q)
Definition: elem_quality.C:42
const MeshBase & mesh() const
Definition: mesh_output.h:234
double abs(double a)
int & strand_offset()
Definition: tecplot_io.C:156
const unsigned int n_vars
Definition: tecplot_io.C:69
long double max(long double a, double b)
std::set< subdomain_id_type > _subdomain_ids
Definition: tecplot_io.h:172
void write_ascii(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
Definition: tecplot_io.C:233
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
OStreamProxy err(std::cerr)
unsigned elem_dimension()
Definition: tecplot_io.C:205
PetscErrorCode ierr
std::string & zone_title()
Definition: tecplot_io.C:163

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

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

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

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

◆ 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_parallel_solution_vector(), libMesh::EquationSystems::build_solution_vector(), libMesh::EquationSystems::build_variable_names(), libMesh::EquationSystems::get_mesh(), 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-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 
67  MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
68 
69  // Build the list of variable names that will be written.
70  std::vector<std::string> names;
71  es.build_variable_names (names, nullptr, system_names);
72 
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  {
84  std::unique_ptr<NumericVector<Number>> parallel_soln =
85  es.build_parallel_solution_vector(system_names);
86 
87  this->write_nodal_data (fname, *parallel_soln, names);
88  }
89 }
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
Definition: mesh_output.h:105
const MeshBase *const _obj
Definition: mesh_output.h:177
OStreamProxy out(std::cout)

◆ write_nodal_data() [1/2]

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.

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

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

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 }
const MeshBase & mesh() const
Definition: mesh_output.h:234
void write_ascii(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
Definition: tecplot_io.C:233
void write_binary(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
Definition: tecplot_io.C:352

◆ write_nodal_data() [2/2]

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 should 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 150 of file mesh_output.C.

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

153 {
154  // This is the fallback implementation for parallel I/O formats that
155  // do not yet implement proper writing in parallel, and instead rely
156  // on the full solution vector being available on all processors.
157  std::vector<Number> soln;
158  parallel_soln.localize(soln);
159  this->write_nodal_data(fname, soln, names);
160 }
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
Definition: mesh_output.h:105
virtual void localize(std::vector< T > &v_local) const =0

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

References _zone_title.

Referenced by write_binary().

164 {
165  return _zone_title;
166 }
std::string _zone_title
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 159 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 168 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: