libMesh
Loading...
Searching...
No Matches
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.
 
virtual void write (const std::string &) override
 This method implements writing a mesh to a specified file.
 
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.
 
bool & binary ()
 Flag indicating whether or not to write a binary file (if the tecio.a library was found by configure).
 
double & time ()
 Solution time for transient data.
 
intstrand_offset ()
 Strand offset for this file.
 
std::string & zone_title ()
 The zone title to write.
 
bool & ascii_append ()
 Set to true to write multiple solutions to a single file (ASCII only).
 
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.
 
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.
 
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.
 
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.
 
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.
 
unsigned intascii_precision ()
 Return/set the precision to use when writing ASCII files.
 

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.
 
const bool _serial_only_needed_on_proc_0
 Flag specifying whether this format can be written by only serializing the mesh to processor zero.
 

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.
 
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.
 
unsigned elem_dimension ()
 Determines the logical spatial dimension of the elements in the Mesh.
 

Private Attributes

bool _binary
 Flag to write binary data.
 
double _time
 Solution time.
 
int _strand_offset
 Offset for Tecplot's STRANDID.
 
std::string _zone_title
 The zone title to write.
 
bool _ascii_append
 If true, when writing in ASCII format, open the file in std::ofstream::app mode.
 
std::set< subdomain_id_type_subdomain_ids
 The subdomains in the mesh.
 
const MeshBase *const _obj
 A pointer to a constant object.
 
unsigned int _ascii_precision
 Precision to use when writing ASCII files.
 

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.

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}
int _strand_offset
Offset for Tecplot's STRANDID.
Definition tecplot_io.h:156
std::set< subdomain_id_type > _subdomain_ids
The subdomains in the mesh.
Definition tecplot_io.h:172
bool _ascii_append
If true, when writing in ASCII format, open the file in std::ofstream::app mode.
Definition tecplot_io.h:167
double _time
Solution time.
Definition tecplot_io.h:151
std::string _zone_title
The zone title to write.
Definition tecplot_io.h:161
bool _binary
Flag to write binary data.
Definition tecplot_io.h:146
template class LIBMESH_EXPORT MeshOutput< MeshBase >

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

169{
170 return _ascii_append;
171}

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

270{
271 return _ascii_precision;
272}
unsigned int _ascii_precision
Precision to use when writing ASCII files.

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

142{
143 return _binary;
144}

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

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}
unsigned int dim
const MT & mesh() const

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

Referenced by write_ascii(), and write_binary().

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

260{
261 libmesh_assert(_obj);
262 return *_obj;
263}
const MeshBase *const _obj
A pointer to a constant object.
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.

156{
157 return _strand_offset;
158}

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

149{
150 return _time;
151}

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

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}
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
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

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

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}
unsigned int n_vars
unsigned int & ascii_precision()
Return/set the precision to use when writing ASCII files.
unsigned elem_dimension()
Determines the logical spatial dimension of the elements in the Mesh.
Definition tecplot_io.C:204
OStreamProxy out
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:176
const dof_id_type n_nodes
Definition tecplot_io.C:67

References _ascii_append, _time, 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::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 351 of file tecplot_io.C.

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}
void ErrorVector unsigned int
std::string & zone_title()
The zone title to write.
Definition tecplot_io.C:162
int & strand_offset()
Strand offset for this file.
Definition tecplot_io.C:155
Tnew cast_int(Told oldvar)
OStreamProxy err
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
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:153
TestClass subdomain_id_type
Based on the 4-byte comment warning above, this probably doesn't work with exodusII at all....
Definition id_types.h:43

References _subdomain_ids, _time, libMesh::as_range(), elem_dimension(), libMesh::err, libMesh::index_range(), libMesh::make_range(), libMesh::MeshOutput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::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().

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

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

◆ 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, and libMesh::ExodusII_IO.

Definition at line 92 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-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
68 if (!_is_parallel_format)
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...

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

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}

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

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

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}

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

163{
164 return _zone_title;
165}

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 207 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 184 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 202 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 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: