libMesh
ensight_io.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // libMesh includes
21 #include "libmesh/dof_map.h"
22 #include "libmesh/ensight_io.h"
23 #include "libmesh/equation_systems.h"
24 #include "libmesh/fe_interface.h"
25 #include "libmesh/libmesh.h"
26 #include "libmesh/system.h"
27 #include "libmesh/elem.h"
28 #include "libmesh/enum_elem_type.h"
29 #include "libmesh/int_range.h"
30 #include "libmesh/utility.h" // map_find
31 
32 // C++ includes
33 #include <sstream>
34 #include <fstream>
35 #include <string>
36 #include <iomanip>
37 
38 namespace libMesh
39 {
40 
41 // Initialize the static data members by calling the static build functions.
42 std::map<ElemType, std::string> EnsightIO::_element_map = EnsightIO::build_element_map();
43 
44 // Static function used to build the _element_map.
45 std::map<ElemType, std::string> EnsightIO::build_element_map()
46 {
47  std::map<ElemType, std::string> ret;
48  ret[EDGE2] = "bar2";
49  ret[EDGE3] = "bar3";
50  ret[QUAD4] = "quad4";
51  ret[QUAD8] = "quad8";
52  // ret[QUAD9] = "quad9"; // not supported
53  ret[TRI3] = "tria3";
54  ret[TRI6] = "tria6";
55  ret[TET4] = "tetra4";
56  ret[TET10] = "tetra10";
57  ret[HEX8] = "hexa8";
58  ret[HEX20] = "hexa20";
59  // ret[HEX27] = "HEX27"; // not supported
60  ret[PYRAMID5] = "pyramid5";
61  return ret;
62 }
63 
64 
65 EnsightIO::EnsightIO (const std::string & filename,
66  const EquationSystems & eq) :
67  MeshOutput<MeshBase> (eq.get_mesh()),
68  _equation_systems(eq)
69 {
71  _ensight_file_name = filename;
72  else
73  {
74  std::ostringstream tmp_file;
75  tmp_file << filename << "_rank" << _equation_systems.processor_id();
76  _ensight_file_name = tmp_file.str();
77  }
78 }
79 
80 
81 
82 void EnsightIO::add_vector (const std::string & system_name,
83  const std::string & vec_description,
84  const std::string & u,
85  const std::string & v)
86 {
88  libmesh_assert (_equation_systems.get_system(system_name).has_variable(u));
89  libmesh_assert (_equation_systems.get_system(system_name).has_variable(v));
90 
91  Vectors vec;
92  vec.description = vec_description;
93  vec.components.push_back(u);
94  vec.components.push_back(v);
95 
96  _system_vars_map[system_name].EnsightVectors.push_back(vec);
97 }
98 
99 
100 
101 void EnsightIO::add_vector (const std::string & system_name,
102  const std::string & vec_name,
103  const std::string & u,
104  const std::string & v,
105  const std::string & w)
106 {
108  libmesh_assert(_equation_systems.get_system(system_name).has_variable(u));
109  libmesh_assert(_equation_systems.get_system(system_name).has_variable(v));
110  libmesh_assert(_equation_systems.get_system(system_name).has_variable(w));
111 
112  Vectors vec;
113  vec.description = vec_name;
114  vec.components.push_back(u);
115  vec.components.push_back(v);
116  vec.components.push_back(w);
117  _system_vars_map[system_name].EnsightVectors.push_back(vec);
118 }
119 
120 
121 
122 void EnsightIO::add_scalar(const std::string & system_name,
123  const std::string & scl_description,
124  const std::string & s)
125 {
127  libmesh_assert(_equation_systems.get_system(system_name).has_variable(s));
128 
129  Scalars scl;
130  scl.description = scl_description;
131  scl.scalar_name = s;
132 
133  _system_vars_map[system_name].EnsightScalars.push_back(scl);
134 }
135 
136 
137 
138 // This method must be implemented as it is pure virtual in
139 // the MeshOutput base class.
140 void EnsightIO::write (const std::string & name)
141 {
142  // We may need to gather a DistributedMesh to output it, making that
143  // const qualifier in our constructor a dirty lie
144  MeshSerializer serialize(const_cast<MeshBase &>(this->mesh()), !_is_parallel_format);
145 
147  this->write();
148 }
149 
150 
151 
153 {
154  this->write_ascii(time);
155  this->write_case();
156 }
157 
158 
159 
161 {
162  _time_steps.push_back(time);
163 
164  this->write_geometry_ascii();
165  this->write_solution_ascii();
166 }
167 
168 
169 
171 {
172  std::ostringstream file;
173  file << _ensight_file_name
174  << ".geo"
175  << std::setw(3)
176  << std::setprecision(0)
177  << std::setfill('0')
178  << std::right
179  << _time_steps.size()-1;
180 
181  // Open a stream to write the mesh
182  std::ofstream mesh_stream(file.str().c_str());
183 
184  mesh_stream << "EnSight Gold Geometry File Format\n";
185  mesh_stream << "Generated by \n";
186  mesh_stream << "node id off\n";
187  mesh_stream << "element id given\n";
188  mesh_stream << "part\n";
189  mesh_stream << std::setw(10) << 1 << "\n";
190  mesh_stream << "uns-elements\n";
191  mesh_stream << "coordinates\n";
192 
193  // mapping between nodal index and your coordinates
194  std::map<int, Point> mesh_nodes_map;
195 
196  // Map for grouping elements of the same type
197  std::map<ElemType, std::vector<const Elem *>> ensight_parts_map;
198 
199  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
200 
201  // Construct the various required maps
202  for (const auto & elem : the_mesh.active_local_element_ptr_range())
203  {
204  ensight_parts_map[elem->type()].push_back(elem);
205 
206  for (const Node & node : elem->node_ref_range())
207  mesh_nodes_map[node.id()] = node;
208  }
209 
210  // Write number of local points
211  mesh_stream << std::setw(10) << mesh_nodes_map.size() << "\n";
212 
213  // write x, y, and z node positions, build mapping between
214  // ensight and libmesh node numbers.
215  std::map <int, int> ensight_node_index;
216  for (unsigned direction=0; direction<3; ++direction)
217  {
218  int i = 1;
219  for (const auto & pr : mesh_nodes_map)
220  {
221  mesh_stream << std::setw(12)
222  << std::setprecision(5)
223  << std::scientific
224  << pr.second(direction)
225  << "\n";
226  ensight_node_index[pr.first] = i++;
227  }
228  }
229 
230  // Write parts
231  for (const auto & pr : ensight_parts_map)
232  {
233  // Look up this ElemType in the map, error if not present.
234  std::string name = libmesh_map_find(_element_map, pr.first);
235 
236  // Write element type
237  mesh_stream << "\n" << name << "\n";
238 
239  const std::vector<const Elem *> & elem_ref = pr.second;
240 
241  // Write number of element
242  mesh_stream << std::setw(10) << elem_ref.size() << "\n";
243 
244  // Write element id
245  for (const auto & elem : elem_ref)
246  mesh_stream << std::setw(10) << elem->id() << "\n";
247 
248  // Write connectivity
249  for (auto i : index_range(elem_ref))
250  {
251  for (const auto & node : elem_ref[i]->node_ref_range())
252  {
253  // tests!
254  if (pr.first == QUAD9 && i==4)
255  continue;
256 
257  // tests!
258  if (pr.first == HEX27 &&
259  (i==4 || i ==10 || i == 12 ||
260  i == 13 || i ==14 || i == 16 || i == 22))
261  continue;
262 
263  mesh_stream << std::setw(10) << ensight_node_index[node.id()];
264  }
265  mesh_stream << "\n";
266  }
267  }
268 }
269 
270 
271 
272 
273 
275 {
276  std::ostringstream case_file;
277  case_file << _ensight_file_name << ".case";
278 
279  // Open a stream for writing the case file.
280  std::ofstream case_stream(case_file.str().c_str());
281 
282  case_stream << "FORMAT\n";
283  case_stream << "type: ensight gold\n\n";
284  case_stream << "GEOMETRY\n";
285  case_stream << "model: 1 " << _ensight_file_name << ".geo" << "***\n";
286 
287  // Write Variable per node section
288  if (!_system_vars_map.empty())
289  case_stream << "\n\nVARIABLE\n";
290 
291  for (const auto & pr : _system_vars_map)
292  {
293  for (const auto & scalar : pr.second.EnsightScalars)
294  case_stream << "scalar per node: 1 "
295  << scalar.description << " "
296  << _ensight_file_name << "_" << scalar.scalar_name << ".scl***\n";
297 
298  for (const auto & vec : pr.second.EnsightVectors)
299  case_stream << "vector per node: 1 "
300  << vec.description << " "
301  << _ensight_file_name << "_" << vec.description << ".vec***\n";
302 
303  // Write time step section
304  if (_time_steps.size() != 0)
305  {
306  case_stream << "\n\nTIME\n";
307  case_stream << "time set: 1\n";
308  case_stream << "number of steps: " << std::setw(10) << _time_steps.size() << "\n";
309  case_stream << "filename start number: " << std::setw(10) << 0 << "\n";
310  case_stream << "filename increment: " << std::setw(10) << 1 << "\n";
311  case_stream << "time values:\n";
312  for (const auto & time : _time_steps)
313  case_stream << std::setw(12) << std::setprecision(5) << std::scientific << time << "\n";
314  }
315  }
316 }
317 
318 
319 // Write scalar and vector solution
321 {
322  for (const auto & pr : _system_vars_map)
323  {
324  for (const auto & scalar : pr.second.EnsightScalars)
325  this->write_scalar_ascii(pr.first,
326  scalar.scalar_name);
327 
328  for (const auto & vec : pr.second.EnsightVectors)
329  this->write_vector_ascii(pr.first,
330  vec.components,
331  vec.description);
332  }
333 }
334 
335 
336 void EnsightIO::write_scalar_ascii(const std::string & sys,
337  const std::string & var_name)
338 {
339  // Construct scalar variable filename
340  std::ostringstream scl_file;
341  scl_file << _ensight_file_name
342  << "_"
343  << var_name
344  << ".scl"
345  << std::setw(3)
346  << std::setprecision(0)
347  << std::setfill('0')
348  << std::right
349  << _time_steps.size()-1;
350 
351  // Open a stream and start writing scalar variable info.
352  std::ofstream scl_stream(scl_file.str().c_str());
353  scl_stream << "Per node scalar value\n";
354  scl_stream << "part\n";
355  scl_stream << std::setw(10) << 1 << "\n";
356  scl_stream << "coordinates\n";
357 
358  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
359  const unsigned int dim = the_mesh.mesh_dimension();
360  const System & system = _equation_systems.get_system(sys);
361  const DofMap & dof_map = system.get_dof_map();
362  int var = system.variable_number(var_name);
363 
364  std::vector<dof_id_type> dof_indices_scl;
365 
366  // Map from node id -> solution value. We end up just writing this
367  // map out in order, not sure what would happen if there were holes
368  // in the numbering...
369  std::map<int, Real> local_soln;
370 
371  std::vector<Number> elem_soln;
372  std::vector<Number> nodal_soln;
373 
374  // Loop over active local elements, construct the nodal solution, and write it to file.
375  for (const auto & elem : the_mesh.active_local_element_ptr_range())
376  {
377  const FEType & fe_type = system.variable_type(var);
378 
379  dof_map.dof_indices (elem, dof_indices_scl, var);
380 
381  elem_soln.resize(dof_indices_scl.size());
382 
383  for (auto i : index_range(dof_indices_scl))
384  elem_soln[i] = system.current_solution(dof_indices_scl[i]);
385 
386  FEInterface::nodal_soln (dim, fe_type, elem, elem_soln, nodal_soln);
387 
388  libmesh_assert_equal_to (nodal_soln.size(), elem->n_nodes());
389 
390 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
391  libmesh_error_msg("Complex-valued Ensight output not yet supported");
392 #endif
393 
394  for (auto n : elem->node_index_range())
395  local_soln[elem->node_id(n)] = libmesh_real(nodal_soln[n]);
396  }
397 
398  for (const auto & pr : local_soln)
399  scl_stream << std::setw(12)
400  << std::setprecision(5)
401  << std::scientific
402  << pr.second
403  << "\n";
404 }
405 
406 
407 void EnsightIO::write_vector_ascii(const std::string & sys,
408  const std::vector<std::string> & vec,
409  const std::string & var_name)
410 {
411  // Construct vector variable filename
412  std::ostringstream vec_file;
413  vec_file << _ensight_file_name
414  << "_"
415  << var_name
416  << ".vec"
417  << std::setw(3)
418  << std::setprecision(0)
419  << std::setfill('0')
420  << std::right
421  << _time_steps.size()-1;
422 
423  // Open a stream and start writing vector variable info.
424  std::ofstream vec_stream(vec_file.str().c_str());
425  vec_stream << "Per vector per value\n";
426  vec_stream << "part\n";
427  vec_stream << std::setw(10) << 1 << "\n";
428  vec_stream << "coordinates\n";
429 
430  // Get a constant reference to the mesh object.
431  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
432 
433  // The dimension that we are running
434  const unsigned int dim = the_mesh.mesh_dimension();
435 
436  const System & system = _equation_systems.get_system(sys);
437 
438  const DofMap & dof_map = system.get_dof_map();
439 
440  const unsigned int u_var = system.variable_number(vec[0]);
441  const unsigned int v_var = system.variable_number(vec[1]);
442  const unsigned int w_var = (dim==3) ? system.variable_number(vec[2]) : 0;
443 
444  std::vector<dof_id_type> dof_indices_u;
445  std::vector<dof_id_type> dof_indices_v;
446  std::vector<dof_id_type> dof_indices_w;
447 
448  // Map from node id -> solution value. We end up just writing this
449  // map out in order, not sure what would happen if there were holes
450  // in the numbering...
451  std::map<int,std::vector<Real>> local_soln;
452 
453  // Now we will loop over all the elements in the mesh.
454  for (const auto & elem : the_mesh.active_local_element_ptr_range())
455  {
456  const FEType & fe_type = system.variable_type(u_var);
457 
458  dof_map.dof_indices (elem, dof_indices_u, u_var);
459  dof_map.dof_indices (elem, dof_indices_v, v_var);
460  if (dim==3)
461  dof_map.dof_indices (elem, dof_indices_w, w_var);
462 
463  std::vector<Number> elem_soln_u;
464  std::vector<Number> elem_soln_v;
465  std::vector<Number> elem_soln_w;
466 
467  std::vector<Number> nodal_soln_u;
468  std::vector<Number> nodal_soln_v;
469  std::vector<Number> nodal_soln_w;
470 
471  elem_soln_u.resize(dof_indices_u.size());
472  elem_soln_v.resize(dof_indices_v.size());
473  if (dim == 3)
474  elem_soln_w.resize(dof_indices_w.size());
475 
476  for (auto i : index_range(dof_indices_u))
477  {
478  elem_soln_u[i] = system.current_solution(dof_indices_u[i]);
479  elem_soln_v[i] = system.current_solution(dof_indices_v[i]);
480  if (dim==3)
481  elem_soln_w[i] = system.current_solution(dof_indices_w[i]);
482  }
483 
484  FEInterface::nodal_soln (dim, fe_type, elem, elem_soln_u, nodal_soln_u);
485  FEInterface::nodal_soln (dim, fe_type, elem, elem_soln_v, nodal_soln_v);
486  if (dim == 3)
487  FEInterface::nodal_soln (dim, fe_type, elem, elem_soln_w, nodal_soln_w);
488 
489  libmesh_assert_equal_to (nodal_soln_u.size(), elem->n_nodes());
490  libmesh_assert_equal_to (nodal_soln_v.size(), elem->n_nodes());
491 
492 #ifdef LIBMESH_ENABLE_COMPLEX
493  libmesh_error_msg("Complex-valued Ensight output not yet supported");
494 #endif
495 
496  for (const auto & n : elem->node_index_range())
497  {
498  std::vector<Real> node_vec(3);
499  node_vec[0] = libmesh_real(nodal_soln_u[n]);
500  node_vec[1] = libmesh_real(nodal_soln_v[n]);
501  node_vec[2] = 0.0;
502  if (dim==3)
503  node_vec[2] = libmesh_real(nodal_soln_w[n]);
504  local_soln[elem->node_id(n)] = node_vec;
505  }
506  }
507 
508  for (unsigned dir=0; dir<3; ++dir)
509  {
510  for (const auto & pr : local_soln)
511  vec_stream << std::setw(12)
512  << std::scientific
513  << std::setprecision(5)
514  << pr.second[dir]
515  << "\n";
516  }
517 }
518 
519 } // namespace libMesh
libMesh::System
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:100
libMesh::HEX20
Definition: enum_elem_type.h:48
libMesh::EnsightIO::Scalars
Definition: ensight_io.h:129
libMesh::EnsightIO::Vectors::description
std::string description
Definition: ensight_io.h:124
eq
PetscBool eq
Definition: petscdmlibmeshimpl.C:1030
libMesh::EnsightIO::_equation_systems
const EquationSystems & _equation_systems
Definition: ensight_io.h:159
libMesh::DofMap::dof_indices
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1967
libMesh::EnsightIO::_ensight_file_name
std::string _ensight_file_name
Definition: ensight_io.h:152
libMesh::EnsightIO::write_vector_ascii
void write_vector_ascii(const std::string &sys, const std::vector< std::string > &vec, const std::string &var_name)
Definition: ensight_io.C:407
libMesh::HEX8
Definition: enum_elem_type.h:47
libMesh::libmesh_real
T libmesh_real(T a)
Definition: libmesh_common.h:166
libMesh::EnsightIO::Vectors
Definition: ensight_io.h:122
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
libMesh::EnsightIO::_element_map
static std::map< ElemType, std::string > _element_map
Definition: ensight_io.h:162
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::TET10
Definition: enum_elem_type.h:46
libMesh::EquationSystems::get_system
const T_sys & get_system(const std::string &name) const
Definition: equation_systems.h:757
libMesh::EnsightIO::_time_steps
std::vector< Real > _time_steps
Definition: ensight_io.h:153
libMesh::EnsightIO::add_scalar
void add_scalar(const std::string &system, const std::string &scalar_description, const std::string &s)
Tell the EnsightIO interface to output the finite element (not SCALAR) variable named "s".
Definition: ensight_io.C:122
libMesh::MeshBase::mesh_dimension
unsigned int mesh_dimension() const
Definition: mesh_base.C:135
libMesh::EquationSystems::has_system
bool has_system(const std::string &name) const
Definition: equation_systems.h:694
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::FEInterface::nodal_soln
static void nodal_soln(const unsigned int dim, const FEType &fe_t, const Elem *elem, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln)
Build the nodal soln from the element soln.
Definition: fe_interface.C:580
libMesh::EnsightIO::write_case
void write_case()
Definition: ensight_io.C:274
libMesh::TET4
Definition: enum_elem_type.h:45
libMesh::System::current_solution
Number current_solution(const dof_id_type global_dof_number) const
Definition: system.C:194
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::HEX27
Definition: enum_elem_type.h:49
libMesh::MeshSerializer
Temporarily serialize a DistributedMesh for output; a distributed mesh is allgathered by the MeshSeri...
Definition: mesh_serializer.h:42
libMesh::ParallelObject::n_processors
processor_id_type n_processors() const
Definition: parallel_object.h:100
libMesh::EnsightIO::write
void write(Real time=0)
Calls write_ascii() and write_case().
Definition: ensight_io.C:152
libMesh::EnsightIO::write_geometry_ascii
void write_geometry_ascii()
Definition: ensight_io.C:170
libMesh::EnsightIO::Scalars::description
std::string description
Definition: ensight_io.h:132
libMesh::MeshOutput< MeshBase >::_is_parallel_format
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
Definition: mesh_output.h:172
libMesh::ParallelObject::processor_id
processor_id_type processor_id() const
Definition: parallel_object.h:106
libMesh::EnsightIO::add_vector
void add_vector(const std::string &system, const std::string &vec_description, const std::string &u, const std::string &v)
Tell the EnsightIO interface that the variables (u,v) constitute a vector.
Definition: ensight_io.C:82
libMesh::QUAD4
Definition: enum_elem_type.h:41
libMesh::TRI3
Definition: enum_elem_type.h:39
libMesh::Node
A Node is like a Point, but with more information.
Definition: node.h:52
libMesh::EnsightIO::EnsightIO
EnsightIO(const std::string &filename, const EquationSystems &eq)
Constructor.
Definition: ensight_io.C:65
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::System::variable_type
const FEType & variable_type(const unsigned int i) const
Definition: system.h:2233
libMesh::EnsightIO::_system_vars_map
std::map< std::string, SystemVars > _system_vars_map
Definition: ensight_io.h:156
libMesh::TRI6
Definition: enum_elem_type.h:40
libMesh::MeshOutput
This class defines an abstract interface for Mesh output.
Definition: mesh_output.h:53
libMesh::EnsightIO::build_element_map
static std::map< ElemType, std::string > build_element_map()
Definition: ensight_io.C:45
libMesh::FEType
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:178
libMesh::MeshOutput< MeshBase >::mesh
const MeshBase & mesh() const
Definition: mesh_output.h:247
libMesh::EnsightIO::write_solution_ascii
void write_solution_ascii()
Definition: ensight_io.C:320
libMesh::PYRAMID5
Definition: enum_elem_type.h:53
libMesh::DofMap
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:176
libMesh::EDGE3
Definition: enum_elem_type.h:36
libMesh::System::variable_number
unsigned short int variable_number(const std::string &var) const
Definition: system.C:1232
libMesh::QUAD9
Definition: enum_elem_type.h:43
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::EnsightIO::write_scalar_ascii
void write_scalar_ascii(const std::string &sys, const std::string &var)
Definition: ensight_io.C:336
libMesh::Quality::name
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
libMesh::EnsightIO::write_ascii
void write_ascii(Real time=0)
Definition: ensight_io.C:160
libMesh::EDGE2
Definition: enum_elem_type.h:35
libMesh::QUAD8
Definition: enum_elem_type.h:42