libMesh
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
libMesh::STLIO Class Reference

This class implements reading and writing triangle meshes in the STL format. More...

#include <stl_io.h>

Inheritance diagram for libMesh::STLIO:
[legend]

Public Member Functions

 STLIO (const MeshBase &)
 Constructor.
 
 STLIO (MeshBase &)
 Constructor.
 
virtual void write (const std::string &) override
 This method implements writing a mesh to a specified file.
 
virtual void read (const std::string &mesh_file) override
 This method implements reading a mesh from a specified file.
 
virtual void read_ascii (std::istream &input)
 This method implements reading a mesh from a specified ASCII input stream.
 
virtual void read_binary (std::istream &input, std::size_t input_size=0)
 This method implements reading a mesh from a specified binary input stream.
 
const std::string & name ()
 This method gets a name after a set or an ASCII read.
 
virtual void set_name (const std::string &name)
 This method sets a name to write.
 
bool subdivide_second_order ()
 Flag indicating whether or not to subdivide second order elements when writing.
 
void set_subdivide_second_order (bool subdivide)
 
bool is_parallel_format () const
 Returns true iff this mesh file format and input class are parallelized, so that all processors can read their share of the data at once.
 
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 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 variable names are provided.
 
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

MeshBasemesh ()
 
void set_n_partitions (unsigned int n_parts)
 Sets the number of partitions in the mesh.
 
void skip_comment_lines (std::istream &in, const char comment_start)
 Reads input from in, skipping all the lines that start with the character comment_start.
 
const MeshBasemesh () const
 
virtual bool get_add_sides ()
 

Protected Attributes

std::vector< bool > elems_of_dimension
 A vector of bools describing what dimension elements have been encountered when reading a mesh.
 
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

std::unique_ptr< std::istream > open_file (const std::string &filename)
 Helper to open possibly-zipped files.
 

Private Attributes

bool _subdivide_second_order
 Flag to subdivide second order elements.
 
std::string _name
 
MeshBase_obj
 A pointer to a non-const object object.
 
const bool _is_parallel_format
 Flag specifying whether this format is parallel-capable.
 
unsigned int _ascii_precision
 Precision to use when writing ASCII files.
 

Detailed Description

This class implements reading and writing triangle meshes in the STL format.

Author
Roy H. Stogner
Date
2024

Definition at line 45 of file stl_io.h.

Constructor & Destructor Documentation

◆ STLIO() [1/2]

libMesh::STLIO::STLIO ( const MeshBase mesh)
explicit

Constructor.

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

Definition at line 64 of file stl_io.C.

64 :
67{
68}
bool _subdivide_second_order
Flag to subdivide second order elements.
Definition stl_io.h:120
template class LIBMESH_EXPORT MeshOutput< MeshBase >

◆ STLIO() [2/2]

libMesh::STLIO::STLIO ( MeshBase mesh)
explicit

Constructor.

Takes a writable reference to a mesh object. This constructor is required to let us read in a mesh.

Definition at line 72 of file stl_io.C.

72 :
73 MeshInput<MeshBase> (mesh),
76{
77}

Member Function Documentation

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

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

◆ is_parallel_format()

bool libMesh::MeshInput< MeshBase >::is_parallel_format ( ) const
inlineinherited

Returns true iff this mesh file format and input class are parallelized, so that all processors can read their share of the data at once.

Definition at line 87 of file mesh_input.h.

87{ return this->_is_parallel_format; }
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
Definition mesh_input.h:130

◆ mesh() [1/2]

MeshBase & libMesh::MeshInput< MeshBase >::mesh ( )
inlineprotectedinherited
Returns
The object as a writable reference.

Definition at line 94 of file mesh_input.h.

179{
180 libmesh_error_msg_if(_obj == nullptr, "ERROR: _obj should not be nullptr!");
181 return *_obj;
182}
MeshBase * _obj
A pointer to a non-const object object.
Definition mesh_input.h:123

◆ mesh() [2/2]

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)

◆ name()

const std::string & libMesh::STLIO::name ( )
inline

This method gets a name after a set or an ASCII read.

Definition at line 94 of file stl_io.h.

94{ return _name; }
std::string _name
Definition stl_io.h:122

References _name.

Referenced by set_name().

◆ open_file()

std::unique_ptr< std::istream > libMesh::STLIO::open_file ( const std::string &  filename)
private

Helper to open possibly-zipped files.

Definition at line 223 of file stl_io.C.

224{
225 const bool gzipped_file = Utility::ends_with(filename, ".gz");
226
227 std::unique_ptr<std::istream> file;
228
229 if (gzipped_file)
230 {
231#ifdef LIBMESH_HAVE_GZSTREAM
232 auto inf = std::make_unique<igzstream>();
233 libmesh_assert(inf);
234 inf->open(filename.c_str(), std::ios::in);
235 file = std::move(inf);
236#else
237 libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
238#endif
239 }
240 else
241 {
242 auto inf = std::make_unique<std::ifstream>();
243 libmesh_assert(inf);
244
245 std::string new_name = Utility::unzip_file(filename);
246
247 inf->open(new_name.c_str(), std::ios::in);
248 file = std::move(inf);
249 }
250
251 return file;
252}
bool ends_with(std::string_view superstring, std::string_view suffix)
Look for a substring at the very end of a string.
Definition utility.C:213
std::string unzip_file(std::string_view name)
Create an unzipped copy of a bz2 or xz file, returning the name of the now-unzipped file that can be ...
Definition utility.C:164

References libMesh::Utility::ends_with(), libMesh::libmesh_assert(), and libMesh::Utility::unzip_file().

Referenced by read().

◆ read()

void libMesh::STLIO::read ( const std::string &  mesh_file)
overridevirtual

This method implements reading a mesh from a specified file.

Implements libMesh::MeshInput< MeshBase >.

Definition at line 165 of file stl_io.C.

166{
167 LOG_SCOPE("read()", "STLIO");
168
169 // This is a serial-only process for now;
170 // the Mesh should be read on processor 0 and
171 // broadcast later
172 libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
173
174 // Clear the mesh so we are sure to start from a pristine state.
175 MeshBase & mesh = MeshInput<MeshBase>::mesh();
176 mesh.clear();
178
179 std::unique_ptr<std::istream> fstream =
180 this->open_file(filename);
181
182 char c;
183 const char * expected_header = "solid!";
184 bool is_ascii_stl = false,
185 is_binary_stl = false;
186 while (fstream->get(c))
187 {
188 if (c == ' ')
189 continue;
190 if (c == *expected_header)
191 {
192 ++expected_header;
193 if (*expected_header == '!')
194 {
195 is_ascii_stl = true;
196 break;
197 }
198 }
199 else
200 {
201 is_binary_stl = true; // probably
202 break;
203 }
204 }
205
206 if (is_ascii_stl)
207 {
208 fstream->seekg(0);
209 this->read_ascii(*fstream);
210 }
211 else if (is_binary_stl)
212 {
213 fstream->seekg(0, std::ios_base::end);
214 std::size_t length = fstream->tellg();
215 fstream->seekg(0);
216 this->read_binary(*fstream, length);
217 }
218 else
219 libmesh_error_msg("Failed to read an STL header in " << filename);
220}
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
Definition mesh_base.h:423
virtual void clear()
Deletes all the element and node data that is currently stored.
Definition mesh_base.C:1036
virtual void read_binary(std::istream &input, std::size_t input_size=0)
This method implements reading a mesh from a specified binary input stream.
Definition stl_io.C:433
std::unique_ptr< std::istream > open_file(const std::string &filename)
Helper to open possibly-zipped files.
Definition stl_io.C:223
virtual void read_ascii(std::istream &input)
This method implements reading a mesh from a specified ASCII input stream.
Definition stl_io.C:256

References libMesh::MeshBase::clear(), libMesh::MeshInput< MT >::mesh(), libMesh::MeshInput< MeshBase >::mesh(), open_file(), read_ascii(), read_binary(), and libMesh::MeshBase::set_mesh_dimension().

Referenced by libMesh::NameBasedIO::read(), MeshInputTest::testGoodSTL(), and MeshInputTest::testGoodSTLBinary().

◆ read_ascii()

void libMesh::STLIO::read_ascii ( std::istream &  input)
virtual

This method implements reading a mesh from a specified ASCII input stream.

Definition at line 256 of file stl_io.C.

257{
258 LOG_SCOPE("read_ascii()", "STLIO");
259
260#ifndef LIBMESH_HAVE_CXX11_REGEX
261 libmesh_not_implemented(); // What is your compiler?!? Email us!
262 libmesh_ignore(file);
263#else
264
265 MeshBase & mesh = MeshInput<MeshBase>::mesh();
266
267 const std::regex all_expected_chars
268 ("^[\\w\\d\\-\\.\\^\\$]*$");
269
270 const std::regex start_regex
271 ("^\\s*solid");
272 const std::regex start_with_name_regex
273 ("^\\s*solid\\s+(\\w+)");
274
275 const std::regex start_facet_regex
276 ("^\\s*facet");
277
278 // We'll ignore facets' normals for now
279 /*
280 const std::regex facet_with_normal_regex
281 ("^\\s*facet\\s+normal"
282 "\\s+([+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+)?|[.]\\d+([eE][+-]?\\d+)?)"
283 "\\s+[+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+)?|[.]\\d+([eE][+-]?\\d+)?)"
284 "\\s+[+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+)?|[.]\\d+([eE][+-]?\\d+)?))");
285 */
286
287 const std::regex start_loop_regex
288 ("^\\s*outer\\s+loop");
289
290 const std::regex vertex_regex
291 ("^\\s*vertex"
292 "\\s+([+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+)?|[.]\\d+([eE][+-]?\\d+)?)"
293 "\\s+[+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+)?|[.]\\d+([eE][+-]?\\d+)?)"
294 "\\s+[+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+)?|[.]\\d+([eE][+-]?\\d+)?))");
295
296 const std::regex end_facet_regex
297 ("^\\s*end\\s*facet");
298
299 const std::regex end_loop_regex
300 ("^\\s*end\\s*loop");
301
302 bool have_started = false;
303 bool in_facet = false;
304 bool in_vertex_loop = false;
305 std::unique_ptr<Tri3> triangle;
306 int next_vertex = 0;
307 int line_num = 0;
308
309 std::unordered_map<Point, Node *> mesh_points;
310
311 for (std::string line; std::getline(file, line);)
312 {
313 ++line_num;
314 std::smatch sm;
315
316 for (char & c : line)
317 {
318 libmesh_error_msg_if
319 (c != '\n' && c != '\r' &&
320 (c < ' ' || c > '~'),
321 "Found non-ASCII character " << int(c) << " on line " <<
322 line_num << "\nSTLIO does not yet support binary files.");
323 }
324
325 if (std::regex_search(line, sm, start_regex))
326 {
327 if (std::regex_search(line, sm, start_with_name_regex))
328 this->_name = sm[1];
329 libmesh_error_msg_if
330 (have_started,
331 "Found two 'solid' lines starting the same STL file?");
332 have_started = true;
333 }
334
335 else if (std::regex_search(line, sm, start_facet_regex))
336 {
337 libmesh_error_msg_if
338 (in_facet,
339 "Found a repeated 'facet' line with no 'endfacet' between them.");
340 in_facet = true;
341
342 /*
343 if (std::regex_search(line, sm, facet_with_normal_regex))
344 {
345 const std::string normalvec = sm[1];
346
347 // Try to be compatible with higher-than-double T; maybe
348 // *someone* out there is doing STL in 128 bits? ...
349 std::stringstream ss(normalvec);
350 ss >> normal(0);
351 ss >> normal(1);
352 ss >> normal(2);
353 }
354 */
355 }
356
357 else if (std::regex_search(line, end_facet_regex))
358 {
359 libmesh_error_msg_if
360 (!in_facet,
361 "Found an 'endfacet' line with no matching 'facet'.");
362 in_facet = false;
363 }
364
365 else if (std::regex_search(line, start_loop_regex))
366 {
367 libmesh_error_msg_if
368 (!in_facet,
369 "Found an 'outer loop' line with no matching 'facet'.");
370 libmesh_error_msg_if
371 (in_vertex_loop,
372 "Found a repeated 'outer loop' line with no 'endloop' between them.");
373 in_vertex_loop = true;
374 triangle = std::make_unique<Tri3>();
375 next_vertex = 0;
376 }
377
378 else if (std::regex_search(line, sm, vertex_regex))
379 {
380 const std::string normalvec = sm[1];
381
382 // Try to be compatible with higher-than-double-precision T;
383 // maybe *someone* out there is doing STL in 128 bits? ...
384 std::stringstream ss(normalvec);
385 Point p;
386 ss >> p(0);
387 ss >> p(1);
388 ss >> p(2);
389
390 Node * node;
391 if (auto it = mesh_points.find(p); it != mesh_points.end())
392 {
393 node = it->second;
394 }
395 else
396 {
397 node = mesh.add_point(p);
398 mesh_points[p] = node;
399 }
400
401 libmesh_error_msg_if
402 (next_vertex > 2,
403 "Found more than 3 vertices in a loop; STLIO only supports Tri3.");
404 triangle->set_node(next_vertex++, node);
405 }
406
407 else if (std::regex_search(line, end_loop_regex))
408 {
409 libmesh_error_msg_if
410 (next_vertex != 3,
411 "Found an 'endloop' line after only seeing " << next_vertex << " vertices in 'loop'.");
412 libmesh_error_msg_if
413 (!in_vertex_loop,
414 "Found an 'endloop' line with no matching 'loop'.");
415 in_vertex_loop = false;
416
417 test_and_add(std::move(triangle), mesh);
418 }
419 }
420
421 libmesh_error_msg_if
422 (in_facet,
423 "File ended without ending a facet first.");
424
425 libmesh_error_msg_if
426 (in_vertex_loop,
427 "File ended without ending an outer loop first.");
428#endif // LIBMESH_HAVE_CXX11_REGEX
429}
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
void libmesh_ignore(const Args &...)

References _name, libMesh::MeshBase::add_point(), libMesh::libmesh_ignore(), libMesh::MeshInput< MT >::mesh(), and libMesh::MeshInput< MeshBase >::mesh().

Referenced by read().

◆ read_binary()

void libMesh::STLIO::read_binary ( std::istream &  input,
std::size_t  input_size = 0 
)
virtual

This method implements reading a mesh from a specified binary input stream.

If the size in bytes is known a priori then it can be passed in to allow for additional error checking.

Definition at line 433 of file stl_io.C.

435{
436 LOG_SCOPE("read_binary()", "STLIO");
437
438 MeshBase & mesh = MeshInput<MeshBase>::mesh();
439
440 char header_buffer[80];
441
442 // 80-character header which is generally ignored - Wikipedia
443 file.read(header_buffer, 80);
444
445 // What's our endianness here? Input binary files are specified to
446 // be little endian, and we might need to do conversions.
447
448 uint32_t test_int = 0x87654321;
449 const bool big_endian = ((*reinterpret_cast<char *>(&test_int)) != 0x21);
450 const Utility::ReverseBytes endian_fix{big_endian};
451
452 // C++ doesn't specify a size for float, but we really need 4-byte
453 // floats here. Fortunately basically every implementation ever
454 // uses exactly 4 bytes for float.
455 if constexpr (sizeof(float) != 4)
456 libmesh_error_msg("Trying to read 4 byte floats without 4-byte float?");
457
458 uint32_t n_elem = 0;
459
460 file.read(reinterpret_cast<char*>(&n_elem), 4);
461 endian_fix(n_elem);
462
463 libmesh_error_msg_if
464 (input_size &&
465 (input_size < 84+n_elem*50),
466 "Not enough data for " << n_elem << " STL triangles in " <<
467 input_size << " uncompressed bytes.");
468
469 std::unique_ptr<Tri3> triangle;
470 std::unordered_map<Point, Node *> mesh_points;
471
472 for (unsigned int e : make_range(n_elem))
473 {
475
476 triangle = std::make_unique<Tri3>();
477
478 // We'll ignore facets' normals for now
479 char ignored_buffer[12];
480 file.read(ignored_buffer, 12);
481
482 // Read vertex locations
483 for (int i : make_range(3))
484 {
485 float point_buffer[3];
486 file.read(reinterpret_cast<char*>(point_buffer), 12);
487 endian_fix(point_buffer[0]);
488 endian_fix(point_buffer[1]);
489 endian_fix(point_buffer[2]);
490 const Point p {point_buffer[0],
491 point_buffer[1],
492 point_buffer[2]};
493
494 Node * node;
495 if (auto it = mesh_points.find(p); it != mesh_points.end())
496 {
497 node = it->second;
498 }
499 else
500 {
501 node = mesh.add_point(p);
502 mesh_points[p] = node;
503 }
504
505 triangle->set_node(i, node);
506 }
507
508 // The 2-byte "attribute byte count" is unstandardized; typically
509 // 0, or sometimes triangle color. Ignore it.
510 file.read(ignored_buffer, 2);
511
512 test_and_add(std::move(triangle), mesh);
513 }
514}
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
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

References libMesh::MeshBase::add_point(), libMesh::libmesh_ignore(), libMesh::make_range(), libMesh::MeshInput< MT >::mesh(), and libMesh::MeshInput< MeshBase >::mesh().

Referenced by read().

◆ set_n_partitions()

void libMesh::MeshInput< MeshBase >::set_n_partitions ( unsigned int  n_parts)
inlineprotectedinherited

Sets the number of partitions in the mesh.

Typically this gets done by the partitioner, but some parallel file formats begin "pre-partitioned".

Definition at line 101 of file mesh_input.h.

101{ this->mesh().set_n_partitions() = n_parts; }
MeshBase & mesh

◆ set_name()

virtual void libMesh::STLIO::set_name ( const std::string &  name)
inlinevirtual

This method sets a name to write.

Definition at line 99 of file stl_io.h.

99{ _name = name; }
const std::string & name()
This method gets a name after a set or an ASCII read.
Definition stl_io.h:94

References _name, and name().

◆ set_subdivide_second_order()

void libMesh::STLIO::set_subdivide_second_order ( bool  subdivide)
inline

Definition at line 107 of file stl_io.h.

108 { _subdivide_second_order = subdivide; }

References _subdivide_second_order.

◆ skip_comment_lines()

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.

Definition at line 113 of file mesh_input.h.

189{
190 char c, line[256];
191
192 while (in.get(c), c==comment_start)
193 in.getline (line, 255);
194
195 // put back first character of
196 // first non-comment line
197 in.putback (c);
198}

◆ subdivide_second_order()

bool libMesh::STLIO::subdivide_second_order ( )
inline

Flag indicating whether or not to subdivide second order elements when writing.

This option is not yet supported.

Definition at line 105 of file stl_io.h.

105{ return _subdivide_second_order; }

References _subdivide_second_order.

◆ write()

void libMesh::STLIO::write ( const std::string &  fname)
overridevirtual

This method implements writing a mesh to a specified file.

We currently only support ASCII writes.

Implements libMesh::MeshOutput< MeshBase >.

Definition at line 81 of file stl_io.C.

82{
83 LOG_SCOPE("write()", "STLIO");
84
85 // Get a reference to the mesh
86 const MeshBase * mesh_ptr = &MeshOutput<MeshBase>::mesh();
87
88 libmesh_parallel_only(mesh_ptr->comm());
89
90 // If necessary, serialize to proc 0, which will do all the writing
91 std::unique_ptr<DistributedMesh> mesh_copy;
92 std::unique_ptr<MeshSerializer> serializer;
93 if (!mesh_ptr->is_serial())
94 {
95 mesh_copy = std::make_unique<DistributedMesh>(*mesh_ptr);
96 mesh_ptr = mesh_copy.get();
97 serializer = std::make_unique<MeshSerializer>(*mesh_copy, true, true);
98 }
99
100 const MeshBase & mesh = *mesh_ptr;
101
102 if (mesh.processor_id() != 0)
103 return;
104
105 // Open the output file stream
106 std::ofstream out_stream (fname.c_str());
107
108 out_stream << std::setprecision(this->ascii_precision());
109
110 // Make sure it opened correctly
111 if (!out_stream.good())
112 libmesh_file_error(fname.c_str());
113
114 // Write the header
115 out_stream << "solid " << this->_name << '\n';
116
117 // Write all our triangles
118 // scream if we see a non-triangle
119 for (auto elem : mesh.element_ptr_range())
120 {
121 // Get to this later
122 if (elem->type() == TRI6 || elem->type() == TRI7)
123 {
124 if (this->_subdivide_second_order)
125 libmesh_not_implemented();
126
127 libmesh_error_msg("Tried to write a non-linear triangle to an STL file");
128 }
129
130 libmesh_error_msg_if(elem->type() != TRI3,
131 "Tried to write a non-triangle to an STL file");
132
133 auto n = (elem->point(1)-elem->point(0)).cross(elem->point(2)-elem->point(0));
134
135 // Other STL files have slivers, I guess ours can too
136 if (auto length = n.norm())
137 n /= length;
138
139 out_stream << "facet normal " <<
140 n(0) << ' ' <<
141 n(1) << ' ' <<
142 n(2) << "\n"
143 " outer loop\n"
144 " vertex " <<
145 elem->point(0)(0) << ' ' <<
146 elem->point(0)(1) << ' ' <<
147 elem->point(0)(2) << "\n"
148 " vertex " <<
149 elem->point(1)(0) << ' ' <<
150 elem->point(1)(1) << ' ' <<
151 elem->point(1)(2) << "\n"
152 " vertex " <<
153 elem->point(2)(0) << ' ' <<
154 elem->point(2)(1) << ' ' <<
155 elem->point(2)(2) << "\n"
156 " endloop\n"
157 "endfacet\n";
158 }
159
160 out_stream << "endsolid" << std::endl;
161}
unsigned int & ascii_precision()
Return/set the precision to use when writing ASCII files.
const MT & mesh() const
processor_id_type processor_id() const

References _name, _subdivide_second_order, libMesh::MeshOutput< MeshBase >::ascii_precision(), libMesh::ParallelObject::comm(), libMesh::MeshBase::is_serial(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshOutput< MT >::mesh(), libMesh::ParallelObject::processor_id(), libMesh::TRI3, libMesh::TRI6, and libMesh::TRI7.

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

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

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

virtual void libMesh::MeshOutput< MeshBase >::write_nodal_data ( const std::string &  ,
const std::vector< Number > &  ,
const std::vector< std::string > &   
)
inlinevirtualinherited

This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are provided.

Reimplemented in libMesh::ExodusII_IO, libMesh::GmshIO, libMesh::GMVIO, libMesh::GnuPlotIO, libMesh::MEDITIO, libMesh::NameBasedIO, libMesh::TecplotIO, libMesh::VTKIO, libMesh::Nemesis_IO, and libMesh::UCDIO.

Definition at line 109 of file mesh_output.h.

112 { libmesh_not_implemented(); }

◆ 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(); }

Member Data Documentation

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

◆ _is_parallel_format [1/2]

const bool libMesh::MeshInput< MeshBase >::_is_parallel_format
privateinherited

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 130 of file mesh_input.h.

◆ _is_parallel_format [2/2]

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.

◆ _name

std::string libMesh::STLIO::_name
private

Definition at line 122 of file stl_io.h.

Referenced by name(), read_ascii(), set_name(), and write().

◆ _obj

MeshBase * libMesh::MeshInput< MeshBase >::_obj
privateinherited

A pointer to a non-const object object.

This allows us to read the object from file.

Definition at line 123 of file mesh_input.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.

◆ _subdivide_second_order

bool libMesh::STLIO::_subdivide_second_order
private

Flag to subdivide second order elements.

Definition at line 120 of file stl_io.h.

Referenced by set_subdivide_second_order(), subdivide_second_order(), and write().

◆ elems_of_dimension

std::vector<bool> libMesh::MeshInput< MeshBase >::elems_of_dimension
protectedinherited

A vector of bools describing what dimension elements have been encountered when reading a mesh.

Definition at line 107 of file mesh_input.h.


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