libMesh::GmshIO Class Reference

#include <gmsh_io.h>

Inheritance diagram for libMesh::GmshIO:

Public Member Functions

 GmshIO (MeshBase &mesh)
 
 GmshIO (const MeshBase &mesh)
 
virtual void read (const std::string &name)
 
virtual void write (const std::string &name)
 
virtual void write_nodal_data (const std::string &, const std::vector< Number > &, const std::vector< std::string > &)
 
bool & binary ()
 
virtual void write_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=NULL)
 
unsigned int & ascii_precision ()
 

Protected Member Functions

MeshBasemesh ()
 
void skip_comment_lines (std::istream &in, const char comment_start)
 
const MeshBasemesh () const
 

Protected Attributes

std::vector< bool > elems_of_dimension
 
const bool _is_parallel_format
 

Private Member Functions

virtual void read_mesh (std::istream &in)
 
virtual void write_mesh (std::ostream &out)
 
void write_post (const std::string &, const std::vector< Number > *=NULL, const std::vector< std::string > *=NULL)
 

Private Attributes

bool _binary
 

Detailed Description

This class implements writing meshes in the Gmsh format. For a full description of the Gmsh format and to obtain the GMSH software see the Gmsh home page

Author
John W. Peterson, 2004
Martin Lüthi, 2005 (support for reading meshes and writing results)

Definition at line 51 of file gmsh_io.h.

Constructor & Destructor Documentation

libMesh::GmshIO::GmshIO ( MeshBase mesh)
inlineexplicit

Constructor. Takes a non-const Mesh reference which it will fill up with elements via the read() command.

Definition at line 153 of file gmsh_io.h.

153  :
154  MeshInput<MeshBase> (mesh),
155  MeshOutput<MeshBase> (mesh),
156  _binary (false)
157 {}
libMesh::GmshIO::GmshIO ( const MeshBase mesh)
inlineexplicit

Constructor. Takes a reference to a constant mesh object. This constructor will only allow us to write the mesh.

Definition at line 145 of file gmsh_io.h.

145  :
146  MeshOutput<MeshBase> (mesh),
147  _binary (false)
148 {
149 }

Member Function Documentation

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

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.

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

bool & libMesh::GmshIO::binary ( )
inline

Flag indicating whether or not to write a binary file. While binary files may end up being smaller than equivalent ASCII files, they will almost certainly take longer to write. The reason for this is that the ostream::write() function which is used to write "binary" data to streams, only takes a pointer to char as its first argument. This means if you want to write anything other than a buffer of chars, you first have to use a strange memcpy hack to get the data into the desired format. See the templated to_binary_stream() function below.

Definition at line 160 of file gmsh_io.h.

References _binary.

Referenced by write_post().

161 {
162  return _binary;
163 }
MeshBase & libMesh::MeshInput< MeshBase >::mesh ( )
protectedinherited

Returns the object as a writeable reference.

Referenced by libMesh::GMVIO::_read_one_cell(), libMesh::VTKIO::cells_to_vtk(), libMesh::TetGenIO::element_in(), libMesh::UNVIO::element_in(), libMesh::UNVIO::element_out(), libMesh::TetGenIO::node_in(), libMesh::UNVIO::node_in(), libMesh::UNVIO::node_out(), libMesh::VTKIO::nodes_to_vtk(), libMesh::ExodusII_IO::read(), libMesh::Nemesis_IO::read(), libMesh::GMVIO::read(), libMesh::CheckpointIO::read(), libMesh::XdrIO::read(), libMesh::VTKIO::read(), libMesh::LegacyXdrIO::read_ascii(), libMesh::CheckpointIO::read_bcs(), libMesh::CheckpointIO::read_connectivity(), libMesh::UCDIO::read_implementation(), read_mesh(), libMesh::CheckpointIO::read_nodes(), libMesh::CheckpointIO::read_nodesets(), libMesh::XdrIO::read_serialized_bcs(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::OFFIO::read_stream(), libMesh::MatlabIO::read_stream(), libMesh::CheckpointIO::read_subdomain_names(), libMesh::TetGenIO::write(), libMesh::ExodusII_IO::write(), libMesh::Nemesis_IO::write(), libMesh::CheckpointIO::write(), libMesh::XdrIO::write(), libMesh::GMVIO::write_ascii_new_impl(), libMesh::GMVIO::write_ascii_old_impl(), libMesh::CheckpointIO::write_bcs(), libMesh::GMVIO::write_binary(), libMesh::CheckpointIO::write_connectivity(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::UCDIO::write_implementation(), libMesh::UNVIO::write_implementation(), write_mesh(), libMesh::UCDIO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::Nemesis_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_common(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::CheckpointIO::write_nodes(), libMesh::CheckpointIO::write_nodesets(), libMesh::XdrIO::write_parallel(), write_post(), libMesh::XdrIO::write_serialized_bcs(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), and libMesh::CheckpointIO::write_subdomain_names().

void libMesh::GmshIO::read ( const std::string &  name)
virtual

Reads in a mesh in the Gmsh *.msh format from the ASCII file given by name.

Note that for this method to work (in 2d and 3d) you have to explicitly set the mesh dimension prior to calling GmshIO::read() and that Mesh::prepare_for_use() must be called after reading the mesh and before using it.

Implements libMesh::MeshInput< MeshBase >.

Definition at line 315 of file gmsh_io.C.

References read_mesh().

Referenced by libMesh::UnstructuredMesh::read().

316 {
317  std::ifstream in (name.c_str());
318  this->read_mesh (in);
319 }
void libMesh::GmshIO::read_mesh ( std::istream &  in)
privatevirtual

Implementation of the read() function. This function is called by the public interface function and implements reading the file.

Read the element block

If the element dimension is smaller than the mesh dimension, this is a boundary element and will be added to mesh.boundary_info.

Because the elements might not yet exist, the sides are put on hold until the elements are created, and inserted once reading elements is finished

add the boundary element nodes to the set of nodes

If the element yet another dimension, just read in the nodes and throw them away

If any lower dimensional elements have been found in the file, try to add them to the mesh.boundary_info as sides and nodes with the respecitve id's (called "physical" in Gmsh).

Definition at line 322 of file gmsh_io.C.

References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_point(), libMesh::MeshBase::boundary_info, libMesh::Elem::build(), libMesh::Elem::build_side(), libMesh::MeshBase::clear(), libMesh::dim, end, libMesh::err, libMesh::libmesh_assert(), libMesh::MeshInput< MT >::mesh(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::mesh_dimension(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor(), libMesh::MeshBase::node_ptr(), libMesh::processor_id(), libMesh::Real, libMesh::MeshBase::reserve_elem(), libMesh::MeshBase::reserve_nodes(), libMesh::DofObject::set_id(), libMesh::Elem::set_node(), side, and libMesh::Elem::subdomain_id().

Referenced by read().

323 {
324  // This is a serial-only process for now;
325  // the Mesh should be read on processor 0 and
326  // broadcast later
327  libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
328 
329  libmesh_assert(in.good());
330 
331  // initialize the map with element types
332  init_eletypes();
333 
334  // clear any data in the mesh
336  mesh.clear();
337 
338  const unsigned int dim = mesh.mesh_dimension();
339 
340  // some variables
341  const int bufLen = 256;
342  char buf[bufLen+1];
343  int format=0, size=0;
344  Real version = 1.0;
345 
346  // map to hold the node numbers for translation
347  // note the the nodes can be non-consecutive
348  std::map<unsigned int, unsigned int> nodetrans;
349 
350  {
351  while (!in.eof()) {
352  in >> buf;
353 
354  if (!std::strncmp(buf,"$MeshFormat",11))
355  {
356  in >> version >> format >> size;
357  if ((version != 2.0) && (version != 2.1) && (version != 2.2)) {
358  // Some notes on gmsh mesh versions:
359  //
360  // Mesh version 2.0 goes back as far as I know. It's not explicitly
361  // mentioned here: http://www.geuz.org/gmsh/doc/VERSIONS.txt
362  //
363  // As of gmsh-2.4.0:
364  // bumped mesh version format to 2.1 (small change in the $PhysicalNames
365  // section, where the group dimension is now required);
366  // [Since we don't even parse the PhysicalNames section at the time
367  // of this writing, I don't think this change affects us.]
368  //
369  // Mesh version 2.2 tested by Manav Bhatia; no other
370  // libMesh code changes were required for support
371  libMesh::err << "Error: Wrong msh file version " << version << "\n";
372  libmesh_error();
373  }
374  if(format){
375  libMesh::err << "Error: Unknown data format for mesh\n";
376  libmesh_error();
377  }
378  }
379 
380  // read the node block
381  else if (!std::strncmp(buf,"$NOD",4) ||
382  !std::strncmp(buf,"$NOE",4) ||
383  !std::strncmp(buf,"$Nodes",6)
384  )
385  {
386  unsigned int numNodes = 0;
387  in >> numNodes;
388  mesh.reserve_nodes (numNodes);
389 
390  // read in the nodal coordinates and form points.
391  Real x, y, z;
392  unsigned int id;
393 
394  // add the nodal coordinates to the mesh
395  for (unsigned int i=0; i<numNodes; ++i)
396  {
397  in >> id >> x >> y >> z;
398  mesh.add_point (Point(x, y, z), i);
399  nodetrans[id] = i;
400  }
401  // read the $ENDNOD delimiter
402  in >> buf;
403  }
404 
415  else if (!std::strncmp(buf,"$ELM",4) ||
416  !std::strncmp(buf,"$Elements",9)
417  )
418  {
419  unsigned int numElem = 0;
420  std::vector< boundaryElementInfo > boundary_elem;
421 
422  // read how many elements are there, and reserve space in the mesh
423  in >> numElem;
424  mesh.reserve_elem (numElem);
425 
426  // read the elements
427  unsigned int elem_id_counter = 0;
428  for (unsigned int iel=0; iel<numElem; ++iel)
429  {
430  unsigned int id, type, physical, elementary,
431  /* partition = 1,*/ nnodes, ntags;
432  // note - partition was assigned but never used - BSK
433  if(version <= 1.0)
434  {
435  in >> id >> type >> physical >> elementary >> nnodes;
436  }
437  else
438  {
439  in >> id >> type >> ntags;
440  elementary = physical = /* partition = */ 1;
441  for(unsigned int j = 0; j < ntags; j++)
442  {
443  int tag;
444  in >> tag;
445  if(j == 0)
446  physical = tag;
447  else if(j == 1)
448  elementary = tag;
449  // else if(j == 2)
450  // partition = tag;
451  // ignore any other tags for now
452  }
453  }
454 
455  // consult the import element table which element to build
456  const elementDefinition& eletype = eletypes_imp[type];
457  nnodes = eletype.nnodes;
458 
459  // only elements that match the mesh dimension are added
460  // if the element dimension is one less than dim, the nodes and
461  // sides are added to the mesh.boundary_info
462  if (eletype.dim == dim)
463  {
464  // add the elements to the mesh
465  Elem* elem = Elem::build(eletype.type).release();
466  elem->set_id(elem_id_counter);
467  mesh.add_elem(elem);
468 
469  // different to iel, lower dimensional elems aren't added
470  elem_id_counter++;
471 
472  // check number of nodes. We cannot do that for version 2.0
473  if (version <= 1.0)
474  {
475  if (elem->n_nodes() != nnodes)
476  {
477  libMesh::err << "Number of nodes for element " << id
478  << " of type " << eletypes_imp[type].type
479  << " (Gmsh type " << type
480  << ") does not match Libmesh definition. "
481  << "I expected " << elem->n_nodes()
482  << " nodes, but got " << nnodes << "\n";
483  libmesh_error();
484  }
485  }
486 
487  // add node pointers to the elements
488  int nod = 0;
489  // if there is a node translation table, use it
490  if (eletype.nodes.size() > 0)
491  for (unsigned int i=0; i<nnodes; i++)
492  {
493  in >> nod;
494  elem->set_node(eletype.nodes[i]) = mesh.node_ptr(nodetrans[nod]);
495  }
496  else
497  {
498  for (unsigned int i=0; i<nnodes; i++)
499  {
500  in >> nod;
501  elem->set_node(i) = mesh.node_ptr(nodetrans[nod]);
502  }
503  }
504 
505  // Finally, set the subdomain ID to physical
506  elem->subdomain_id() = static_cast<subdomain_id_type>(physical);
507  } // if element.dim == dim
508  // if this is a boundary
509  else if (eletype.dim == dim-1)
510  {
515  boundaryElementInfo binfo;
516  std::set<dof_id_type>::iterator iter = binfo.nodes.begin();
517  int nod = 0;
518  for (unsigned int i=0; i<nnodes; i++)
519  {
520  in >> nod;
521  mesh.boundary_info->add_node(nodetrans[nod], physical);
522  binfo.nodes.insert(iter, nodetrans[nod]);
523  }
524  binfo.id = physical;
525  boundary_elem.push_back(binfo);
526  }
531  else
532  {
533  static bool seen_high_dim_element = false;
534  if (!seen_high_dim_element)
535  {
536  libMesh::err << "Warning: can't load an element of dimension "
537  << eletype.dim << " into a mesh of dimension "
538  << dim << std::endl;
539  seen_high_dim_element = true;
540  }
541  int nod = 0;
542  for (unsigned int i=0; i<nnodes; i++)
543  in >> nod;
544  }
545  }//element loop
546  // read the $ENDELM delimiter
547  in >> buf;
548 
554  if (boundary_elem.size() > 0)
555  {
556  // create a index of the boundary nodes to easily locate which
557  // element might have that boundary
558  std::map<dof_id_type, std::vector<unsigned int> > node_index;
559  for (unsigned int i=0; i<boundary_elem.size(); i++)
560  {
561  boundaryElementInfo binfo = boundary_elem[i];
562  std::set<dof_id_type>::iterator iter = binfo.nodes.begin();
563  for (;iter!= binfo.nodes.end(); iter++)
564  node_index[*iter].push_back(i);
565  }
566 
569 
570  // iterate over all elements and see which boundary element has
571  // the same set of nodes as on of the boundary elements previously read
572  for ( ; it != end; ++it)
573  {
574  const Elem* elem = *it;
575  for (unsigned int s=0; s<elem->n_sides(); s++)
576  if (elem->neighbor(s) == NULL)
577  {
578  AutoPtr<Elem> side (elem->build_side(s));
579  std::set<dof_id_type> side_nodes;
580  std::set<dof_id_type>::iterator iter = side_nodes.begin();
581 
582  // make a set with all nodes from this side
583  // this allows for easy comparison
584  for (unsigned int ns=0; ns<side->n_nodes(); ns++)
585  side_nodes.insert(iter, side->node(ns));
586 
587  // See whether one of the side node occurs in the list
588  // of tagged nodes. If we would loop over all side
589  // nodes, we would just get multiple hits, so taking
590  // node 0 is enough to do the job
591  dof_id_type sn = side->node(0);
592  if (node_index.count(sn) > 0)
593  {
594  // Loop over all tagged ("physical") "sides" which
595  // contain the node sn (typically just 1 to
596  // three). For each of these the set of nodes is
597  // compared to the current element's side nodes
598  for (std::size_t n=0; n<node_index[sn].size(); n++)
599  {
600  unsigned int bidx = node_index[sn][n];
601  if (boundary_elem[bidx].nodes == side_nodes)
602  mesh.boundary_info->add_side(elem, s, boundary_elem[bidx].id);
603  }
604  }
605  } // if elem->neighbor(s) == NULL
606  } // element loop
607  } // if boundary_elem.size() > 0
608  } // if $ELM
609 
610  } // while !in.eof()
611 
612  }
613 
614 }
void libMesh::MeshInput< MeshBase >::skip_comment_lines ( std::istream &  in,
const char  comment_start 
)
protectedinherited

Reads input from in, skipping all the lines that start with the character comment_start.

Referenced by libMesh::TetGenIO::read(), and libMesh::UCDIO::read_implementation().

void libMesh::GmshIO::write ( const std::string &  name)
virtual

This method implements writing a mesh to a specified file in the Gmsh *.msh format.

Implements libMesh::MeshOutput< MeshBase >.

Definition at line 618 of file gmsh_io.C.

References libMesh::processor_id(), and write_mesh().

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

619 {
621  {
622  // Open the output file stream
623  std::ofstream out_stream (name.c_str());
624 
625  // Make sure it opened correctly
626  if (!out_stream.good())
627  libmesh_file_error(name.c_str());
628 
629  this->write_mesh (out_stream);
630  }
631 }
virtual void libMesh::MeshOutput< MeshBase >::write_equation_systems ( const std::string &  ,
const EquationSystems ,
const std::set< std::string > *  system_names = NULL 
)
virtualinherited

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

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

void libMesh::GmshIO::write_mesh ( std::ostream &  out)
privatevirtual

This method implements writing a mesh to a specified file. This will write an ASCII *.msh file.

Definition at line 648 of file gmsh_io.C.

References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), end, libMesh::DofObject::id(), libMesh::libmesh_assert(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::mesh(), libMesh::MeshBase::n_active_elem(), libMesh::MeshBase::n_nodes(), libMesh::Elem::n_nodes(), libMesh::Elem::node(), libMesh::MeshBase::node(), libMesh::DofObject::processor_id(), libMesh::Real, libMesh::Elem::subdomain_id(), and libMesh::Elem::type().

Referenced by write().

649 {
650  // Be sure that the stream is valid.
651  libmesh_assert (out_stream.good());
652 
653  // initialize the map with element types
654  init_eletypes();
655 
656  // Get a const reference to the mesh
658 
659  // Note: we are using version 2.0 of the gmsh output format.
660 
661  {
662  // Write the file header.
663  out_stream << "$MeshFormat\n";
664  out_stream << "2.0 0 " << sizeof(Real) << '\n';
665  out_stream << "$EndMeshFormat\n";
666  }
667 
668  {
669  // write the nodes in (n x y z) format
670  out_stream << "$Nodes\n";
671  out_stream << mesh.n_nodes() << '\n';
672 
673  for (unsigned int v=0; v<mesh.n_nodes(); v++)
674  out_stream << mesh.node(v).id()+1 << " "
675  << mesh.node(v)(0) << " "
676  << mesh.node(v)(1) << " "
677  << mesh.node(v)(2) << '\n';
678  out_stream << "$EndNodes\n";
679  }
680 
681  {
682  // write the connectivity
683  out_stream << "$Elements\n";
684  out_stream << mesh.n_active_elem() << '\n';
685 
688 
689  // loop over the elements
690  for ( ; it != end; ++it)
691  {
692  const Elem* elem = *it;
693 
694  // Make sure we have a valid entry for
695  // the current element type.
696  libmesh_assert (eletypes_exp.count(elem->type()));
697 
698  // consult the export element table
699  const elementDefinition& eletype = eletypes_exp[elem->type()];
700 
701  // The element mapper better not require any more nodes
702  // than are present in the current element!
703  libmesh_assert_less_equal (eletype.nodes.size(), elem->n_nodes());
704 
705  // elements ids are 1 based in Gmsh
706  out_stream << elem->id()+1 << " ";
707 
708  // element type
709  out_stream << eletype.exptype;
710 
711  // write the number of tags and
712  // tag1 (physical entity), tag2 (geometric entity), and tag3 (partition entity)
713  out_stream << " 3 "
714  << static_cast<unsigned int>(elem->subdomain_id())
715  << " 1 "
716  << (elem->processor_id()+1) << " ";
717 
718  // if there is a node translation table, use it
719  if (eletype.nodes.size() > 0)
720  for (unsigned int i=0; i < elem->n_nodes(); i++)
721  out_stream << elem->node(eletype.nodes[i])+1 << " "; // gmsh is 1-based
722  // otherwise keep the same node order
723  else
724  for (unsigned int i=0; i < elem->n_nodes(); i++)
725  out_stream << elem->node(i)+1 << " "; // gmsh is 1-based
726  out_stream << "\n";
727  } // element loop
728  out_stream << "$EndElements\n";
729  }
730 }
void libMesh::GmshIO::write_nodal_data ( const std::string &  fname,
const std::vector< Number > &  soln,
const std::vector< std::string > &  names 
)
virtual

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 634 of file gmsh_io.C.

References libMesh::processor_id(), libMesh::START_LOG(), libMesh::STOP_LOG(), and write_post().

637 {
638  START_LOG("write_nodal_data()", "GmshIO");
639 
640  //this->_binary = true;
642  this->write_post (fname, &soln, &names);
643 
644  STOP_LOG("write_nodal_data()", "GmshIO");
645 }
void libMesh::GmshIO::write_post ( const std::string &  fname,
const std::vector< Number > *  v = NULL,
const std::vector< std::string > *  solution_names = NULL 
)
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 or binary *.pos file, depending on the binary flag.

Definition at line 733 of file gmsh_io.C.

References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), binary(), libMeshEnums::EDGE2, libMeshEnums::EDGE3, libMeshEnums::EDGE4, end, libMesh::err, libMeshEnums::HEX20, libMeshEnums::HEX27, libMeshEnums::HEX8, libMesh::libmesh_real(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::mesh(), libMesh::MeshBase::n_nodes(), libMesh::n_vars, libMesh::Elem::n_vertices(), libMesh::Elem::node(), libMesh::out, libMesh::Elem::point(), libMeshEnums::PRISM15, libMeshEnums::PRISM18, libMeshEnums::PRISM6, libMesh::processor_id(), libMeshEnums::PYRAMID5, libMeshEnums::QUAD4, libMeshEnums::QUAD8, libMeshEnums::QUAD9, libMeshEnums::TET10, libMeshEnums::TET4, libMeshEnums::TRI3, and libMeshEnums::TRI6.

Referenced by write_nodal_data().

736 {
737 
738  // Should only do this on processor 0!
739  libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
740 
741  // Create an output stream
742  std::ofstream out_stream(fname.c_str());
743 
744  // Make sure it opened correctly
745  if (!out_stream.good())
746  libmesh_file_error(fname.c_str());
747 
748  // initialize the map with element types
749  init_eletypes();
750 
751  // create a character buffer
752  char buf[80];
753 
754  // Get a constant reference to the mesh.
756 
757  // write the data
758  if ((solution_names != NULL) && (v != NULL))
759  {
760  const unsigned int n_vars =
761  libmesh_cast_int<unsigned int>(solution_names->size());
762 
763  if (!(v->size() == mesh.n_nodes()*n_vars))
764  libMesh::err << "ERROR: v->size()=" << v->size()
765  << ", mesh.n_nodes()=" << mesh.n_nodes()
766  << ", n_vars=" << n_vars
767  << ", mesh.n_nodes()*n_vars=" << mesh.n_nodes()*n_vars
768  << "\n";
769 
770  libmesh_assert_equal_to (v->size(), mesh.n_nodes()*n_vars);
771 
772  // write the header
773  out_stream << "$PostFormat\n";
774  if (this->binary())
775  out_stream << "1.2 1 " << sizeof(double) << "\n";
776  else
777  out_stream << "1.2 0 " << sizeof(double) << "\n";
778  out_stream << "$EndPostFormat\n";
779 
780  // Loop over the elements to see how much of each type there are
781  unsigned int n_points=0, n_lines=0, n_triangles=0, n_quadrangles=0,
782  n_tetrahedra=0, n_hexahedra=0, n_prisms=0, n_pyramids=0;
783  unsigned int n_scalar=0, n_vector=0, n_tensor=0;
784  unsigned int nb_text2d=0, nb_text2d_chars=0, nb_text3d=0, nb_text3d_chars=0;
785 
786  {
789 
790 
791  for ( ; it != end; ++it)
792  {
793  const ElemType elemtype = (*it)->type();
794 
795  switch (elemtype)
796  {
797  case EDGE2:
798  case EDGE3:
799  case EDGE4:
800  {
801  n_lines += 1;
802  break;
803  }
804  case TRI3:
805  case TRI6:
806  {
807  n_triangles += 1;
808  break;
809  }
810  case QUAD4:
811  case QUAD8:
812  case QUAD9:
813  {
814  n_quadrangles += 1;
815  break;
816  }
817  case TET4:
818  case TET10:
819  {
820  n_tetrahedra += 1;
821  break;
822  }
823  case HEX8:
824  case HEX20:
825  case HEX27:
826  {
827  n_hexahedra += 1;
828  break;
829  }
830  case PRISM6:
831  case PRISM15:
832  case PRISM18:
833  {
834  n_prisms += 1;
835  break;
836  }
837  case PYRAMID5:
838  {
839  n_pyramids += 1;
840  break;
841  }
842  default:
843  {
844  libMesh::err << "ERROR: Not existant element type "
845  << (*it)->type() << std::endl;
846  libmesh_error();
847  }
848  }
849  }
850  }
851 
852  // create a view for each variable
853  for (unsigned int ivar=0; ivar < n_vars; ivar++)
854  {
855  std::string varname = (*solution_names)[ivar];
856 
857  // at the moment, we just write out scalar quantities
858  // later this should be made configurable through
859  // options to the writer class
860  n_scalar = 1;
861 
862  // write the variable as a view, and the number of time steps
863  out_stream << "$View\n" << varname << " " << 1 << "\n";
864 
865  // write how many of each geometry type are written
866  out_stream << n_points * n_scalar << " "
867  << n_points * n_vector << " "
868  << n_points * n_tensor << " "
869  << n_lines * n_scalar << " "
870  << n_lines * n_vector << " "
871  << n_lines * n_tensor << " "
872  << n_triangles * n_scalar << " "
873  << n_triangles * n_vector << " "
874  << n_triangles * n_tensor << " "
875  << n_quadrangles * n_scalar << " "
876  << n_quadrangles * n_vector << " "
877  << n_quadrangles * n_tensor << " "
878  << n_tetrahedra * n_scalar << " "
879  << n_tetrahedra * n_vector << " "
880  << n_tetrahedra * n_tensor << " "
881  << n_hexahedra * n_scalar << " "
882  << n_hexahedra * n_vector << " "
883  << n_hexahedra * n_tensor << " "
884  << n_prisms * n_scalar << " "
885  << n_prisms * n_vector << " "
886  << n_prisms * n_tensor << " "
887  << n_pyramids * n_scalar << " "
888  << n_pyramids * n_vector << " "
889  << n_pyramids * n_tensor << " "
890  << nb_text2d << " "
891  << nb_text2d_chars << " "
892  << nb_text3d << " "
893  << nb_text3d_chars << "\n";
894 
895  // if binary, write a marker to identify the endianness of the file
896  if (this->binary())
897  {
898  const int one = 1;
899  std::memcpy(buf, &one, sizeof(int));
900  out_stream.write(buf, sizeof(int));
901  }
902 
903  // the time steps (there is just 1 at the moment)
904  if (this->binary())
905  {
906  double one = 1;
907  std::memcpy(buf, &one, sizeof(double));
908  out_stream.write(buf, sizeof(double));
909  }
910  else
911  out_stream << "1\n";
912 
913  // Loop over the elements and write out the data
916 
917  for ( ; it != end; ++it)
918  {
919  const Elem* elem = *it;
920 
921  // this is quite crappy, but I did not invent that file format!
922  for (unsigned int d=0; d<3; d++) // loop over the dimensions
923  {
924  for (unsigned int n=0; n < elem->n_vertices(); n++) // loop over vertices
925  {
926  const Point vertex = elem->point(n);
927  if (this->binary())
928  {
929  double tmp = vertex(d);
930  std::memcpy(buf, &tmp, sizeof(double));
931  out_stream.write(reinterpret_cast<char *>(buf), sizeof(double));
932  }
933  else
934  out_stream << vertex(d) << " ";
935  }
936  if (!this->binary())
937  out_stream << "\n";
938  }
939 
940  // now finally write out the data
941  for (unsigned int i=0; i < elem->n_vertices(); i++) // loop over vertices
942  if (this->binary())
943  {
944 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
945  libMesh::out << "WARNING: Gmsh::write_post does not fully support "
946  << "complex numbers. Will only write the real part of "
947  << "variable " << varname << std::endl;
948 #endif
949  double tmp = libmesh_real((*v)[elem->node(i)*n_vars + ivar]);
950  std::memcpy(buf, &tmp, sizeof(double));
951  out_stream.write(reinterpret_cast<char *>(buf), sizeof(double));
952  }
953  else
954  {
955 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
956  libMesh::out << "WARNING: Gmsh::write_post does not fully support "
957  << "complex numbers. Will only write the real part of "
958  << "variable " << varname << std::endl;
959 #endif
960  out_stream << libmesh_real((*v)[elem->node(i)*n_vars + ivar]) << "\n";
961  }
962  }
963  if (this->binary())
964  out_stream << "\n";
965  out_stream << "$EndView\n";
966 
967  } // end variable loop (writing the views)
968  }
969 
970 }

Member Data Documentation

bool libMesh::GmshIO::_binary
private

Flag to write binary data.

Definition at line 134 of file gmsh_io.h.

Referenced by binary().

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

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


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

Site Created By: libMesh Developers
Last modified: February 07 2014 16:58:01 UTC

Hosted By:
SourceForge.net Logo