18 #include "libmesh/libmesh_config.h" 32 #include "libmesh/boundary_info.h" 33 #include "libmesh/boundary_mesh.h" 34 #include "libmesh/dof_map.h" 35 #include "libmesh/elem.h" 36 #include "libmesh/elem_quality.h" 37 #include "libmesh/gmv_io.h" 38 #include "libmesh/inf_elem_builder.h" 39 #include "libmesh/libmesh.h" 40 #include "libmesh/mesh.h" 41 #include "libmesh/mesh_modification.h" 42 #include "libmesh/mesh_refinement.h" 43 #include "libmesh/mesh_netgen_interface.h" 44 #include "libmesh/poly2tri_triangulator.h" 45 #include "libmesh/simplex_refiner.h" 46 #include "libmesh/statistics.h" 47 #include "libmesh/string_to_enum.h" 48 #include "libmesh/enum_elem_quality.h" 49 #include "libmesh/getpot.h" 50 #include <libmesh/mesh_smoother_vsmoother.h> 59 void usage(
const std::string & prog_name);
61 int main (
int argc,
char ** argv)
65 unsigned int n_subdomains = 1;
67 unsigned int n_rsteps = 0;
68 Real simplex_refine = 0.;
69 double dist_fact = 0.;
72 bool convert_first_order =
false;
73 unsigned int convert_second_order = 0;
74 bool triangulate =
false;
75 bool simplex_fill =
false;
76 Real desired_measure = 1;
77 bool do_quality =
false;
80 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 81 bool addinfelems =
false;
90 std::vector<std::string> names;
91 std::vector<std::string> output_names;
95 usage(std::string(argv[0]));
98 GetPot command_line (argc, argv);
101 if (command_line.search(2,
"-h",
"-?"))
105 command_line.disable_loop();
106 while (command_line.search(1,
"-i"))
109 tmp = command_line.next(tmp);
110 names.push_back(tmp);
112 command_line.reset_cursor();
115 while (command_line.search(1,
"-o"))
118 tmp = command_line.next(tmp);
119 output_names.push_back(tmp);
121 command_line.enable_loop();
124 if (command_line.search(1,
"-D"))
125 dist_fact = command_line.next(dist_fact);
128 if (command_line.search(1,
"-r"))
131 tmp = command_line.next(tmp);
132 n_rsteps = cast_int<unsigned int>(tmp);
136 if (command_line.search(1,
"-s"))
137 simplex_refine = command_line.next(simplex_refine);
140 if (command_line.search(1,
"-p"))
143 tmp = command_line.next(tmp);
144 n_subdomains = cast_int<unsigned int>(tmp);
148 if (command_line.search(1,
"-V"))
152 if (command_line.search(1,
"-t"))
156 if (command_line.search(1,
"-T"))
159 desired_measure = command_line.next(desired_measure);
163 if (command_line.search(1,
"-q"))
167 tmp = command_line.next(tmp);
169 quality_type = Utility::string_to_enum<ElemQuality>(tmp);
173 if (command_line.search(1,
"-v"))
177 if (command_line.search(1,
"-b"))
181 if (command_line.search(1,
"-1"))
182 convert_first_order =
true;
185 if (command_line.search(1,
"-2"))
186 convert_second_order = 2;
189 if (command_line.search(1,
"-3"))
190 convert_second_order = 22;
192 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 195 if (command_line.search(1,
"-a"))
199 if (command_line.search(1,
"-x"))
201 origin_x.first =
true;
202 origin_x.second = command_line.next(origin_x.second);
206 if (command_line.search(1,
"-y"))
208 origin_y.first =
true;
209 origin_y.second = command_line.next(origin_y.second);
213 if (command_line.search(1,
"-z"))
215 origin_z.first =
true;
216 origin_z.second = command_line.next(origin_z.second);
220 if (command_line.search(1,
"-X"))
222 if (command_line.search(1,
"-Y"))
224 if (command_line.search(1,
"-Z"))
227 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS 237 libMesh::out <<
"Mesh " << names[0] <<
":" << std::endl;
242 for (
unsigned int i=1; i < names.size(); ++i)
245 extra_mesh.
read(names[i]);
249 libMesh::out <<
"Mesh " << names[i] <<
":" << std::endl;
250 extra_mesh.print_info();
251 extra_mesh.get_boundary_info().print_summary();
255 #ifdef LIBMESH_ENABLE_UNIQUE_ID 259 mesh.copy_nodes_and_elements(extra_mesh,
false,
282 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 287 "ERROR: Invalid combination: Building infinite elements\n" 288 "not compatible with writing boundary conditions.");
292 libmesh_error_msg_if((x_sym && !origin_x.first) ||
293 (y_sym && !origin_y.first) ||
294 (z_sym && !origin_z.first),
295 "ERROR: When x-symmetry is requested using -X, then\n" 296 "the option -x <coord> also has to be given.\n" 297 "This holds obviously for y and z, too.");
313 libmesh_error_msg_if((origin_x.first || origin_y.first || origin_z.first) ||
314 (x_sym || y_sym || z_sym),
315 "ERROR: -x/-y/-z/-X/-Y/-Z is only to be used when\n" 316 "the option -a is also specified!");
335 #ifdef LIBMESH_HAVE_NETGEN 340 libmesh_error_msg(
"Requested triangulation of a 2D boundary without Poly2Tri enabled");
345 #ifdef LIBMESH_HAVE_POLY2TRI 352 libmesh_error_msg(
"Requested triangulation of a 1D boundary without Poly2Tri enabled");
367 libMesh::out <<
"Quality bounds for this element type are: (" 374 for (
const auto & elem :
mesh.active_element_ptr_range())
375 sv.push_back(elem->quality(quality_type));
377 const unsigned int n_bins = 10;
382 std::vector<dof_id_type> bad_elts = sv.
cut_below(0.8);
385 <<
" elements below the cutoff." << std::endl;
388 std::vector<dof_id_type> histogram;
391 const bool do_matlab =
true;
395 std::ofstream
out (
"histo.m");
397 out <<
"% This is a sample histogram plot for Matlab." << std::endl;
398 out <<
"bin_members = [" << std::endl;
399 for (
unsigned int i=0; i<n_bins; i++)
402 out <<
"];" << std::endl;
404 std::vector<Real> bin_coords(n_bins);
405 const Real max = *(std::max_element(sv.begin(), sv.end()));
406 const Real min = *(std::min_element(sv.begin(), sv.end()));
407 const Real delta = (max - min) / static_cast<Real>(n_bins);
408 for (
unsigned int i=0; i<n_bins; i++)
409 bin_coords[i] = min + (i * delta) + delta / 2.0 ;
411 out <<
"bin_coords = [" << std::endl;
412 for (
unsigned int i=0; i<n_bins; i++)
413 out << bin_coords[i] << std::endl;
414 out <<
"];" << std::endl;
416 out <<
"bar(bin_coords, bin_members, 1);" << std::endl;
417 out <<
"hold on" << std::endl;
418 out <<
"plot (bin_coords, 0, 'kx');" << std::endl;
419 out <<
"xlabel('Quality (0=Worst, 1=Best)');" << std::endl;
420 out <<
"ylabel('Percentage of elements in each bin');" << std::endl;
421 out <<
"axis([" << min <<
"," << max <<
",0, max(bin_members)]);" << std::endl;
430 if (convert_first_order)
433 libMesh::out <<
"Converting elements to first order counterparts\n";
445 if (convert_second_order > 0)
447 bool second_order_mode =
true;
448 std:: string message =
"Converting elements to second order counterparts";
449 if (convert_second_order == 2)
451 second_order_mode =
false;
452 message +=
", lower version: Quad4 -> Quad8, not Quad9";
455 else if (convert_second_order == 22)
457 second_order_mode =
true;
458 message +=
", highest version: Quad4 -> Quad9";
462 libmesh_error_msg(
"Invalid value, convert_second_order = " << convert_second_order);
483 #ifdef LIBMESH_ENABLE_AMR 490 << n_rsteps <<
" times" 519 if (n_subdomains > 1)
530 if (output_names.size())
541 libMesh::out <<
" Mesh got refined, will write only _active_ elements." << std::endl;
547 mesh.active_elements_begin(),
548 mesh.active_elements_end());
551 for (
auto & output_name : output_names)
552 new_mesh.
write(output_name);
557 for (
auto & output_name : output_names)
573 libmesh_error_msg(
"Invalid value write_bndry = " << write_bndry);
576 for (
auto boundary_name : output_names)
578 boundary_name =
"bndry_" + boundary_name;
579 boundary_mesh.
write(boundary_name);
588 void usage(
const std::string & prog_name)
590 std::ostringstream helpList;
591 helpList <<
"usage:\n" 594 <<
" [options] ...\n" 597 <<
" -i <string> Input file name, one option per file\n" 598 <<
" Multiple files get concatenated" 599 <<
" -o <string> Output file name, one option per file\n" 600 <<
"\n -b Write the boundary conditions\n" 601 <<
" -D <factor> Randomly move interior nodes by D*hmin\n" 602 <<
" -h Print help menu\n" 603 <<
" -p <count> Partition into <count> subdomains\n" 604 <<
" -V Apply the variational mesh smoother\n" 605 #ifdef LIBMESH_ENABLE_AMR 606 <<
" -r <count> Uniformly refine <count> times\n" 608 <<
" -s <volume> Split-edge refine elements exceeding <volume>\n" 609 <<
" -t Convert all elements to triangles/tets\n" 610 <<
" -T <desired elem area/vol> Triangulate/Tetrahedralize the interior\n" 612 <<
" -q <metric> Evaluates the named element quality metric\n" 613 <<
" -1 Converts a mesh of higher order elements\n" 614 <<
" to their first-order counterparts:\n" 615 <<
" Quad8 -> Quad4, Tet10 -> Tet4 etc\n" 616 <<
" -2 Converts a mesh of linear elements\n" 617 <<
" to their second-order counterparts:\n" 618 <<
" Quad4 -> Quad8, Tet4 -> Tet10 etc\n" 619 <<
" -3 Same, but to the highest possible:\n" 620 <<
" Quad4 -> Quad9, Hex8 -> Hex27 etc\n" 621 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 622 <<
"\n -a Add infinite elements\n" 623 <<
" -x <coord> Specify infinite element origin\n" 624 <<
" -y <coord> coordinates. If none given, origin\n" 625 <<
" -z <coord> is determined automatically.\n" 626 <<
" -X When building infinite elements \n" 627 <<
" -Y treat mesh as x/y/z-symmetric.\n" 628 <<
" -Z When -X is given, -x <coord> also\n" 629 <<
" has to be given. Similar for y,z.\n" 633 <<
" This program is used to convert and partition from/to a variety of\n" 634 <<
" formats. File types are inferred from file extensions. For example,\n" 637 <<
" ./meshtool -i in.e -o out.plt\n" 639 <<
" will read a mesh in the ExodusII format (from Cubit, for example)\n" 640 <<
" from the file in.e. It will then write the mesh in the Tecplot\n" 641 <<
" binary format to out.plt.\n" 645 <<
" ./meshtool -i cylinder.msh -i square.xda -o out.e -2\n" 647 <<
" will read the Gmsh formatted mesh file cylinder.msh, concatenate\n" 648 <<
" the elements and nodes (with shifted id numbers) from the libMesh\n" 649 <<
" mesh file square.xda, convert all first-order elements from both\n" 650 <<
" to second-order, and write the combined mesh in Exodus format to\n" 652 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 656 <<
" ./meshtool -i dry.unv -o packed.gmv -a -x 30.5 -y -10.5 -X\n" 658 <<
" will read a Universal file, determine the z-coordinate of the origin\n" 659 <<
" automatically, e.g. z_origin = 3., build infinite elements with the\n" 660 <<
" origin (30.5, -10.5, 3.) on top of volume elements, while preserving\n" 661 <<
" a symmetry plane through (30.5, -10.5, 3.) perpendicular to x.\n" 662 <<
" It is imperative that the origin lies _inside_ the given volume mesh.\n" 663 <<
" If not, infinite elements are not correctly built!\n" 666 <<
" This program supports the I/O formats:\n" 668 <<
" *.cpa -- libMesh ASCII checkpoint format\n" 669 <<
" *.cpr -- libMesh binary checkpoint format,\n" 670 <<
" *.e -- Sandia's ExodusII format\n" 671 <<
" *.exd -- Sandia's ExodusII format\n" 672 <<
" *.gmv -- LANL's GMV (General Mesh Viewer) format\n" 673 <<
" *.mesh -- MEdit mesh format\n" 674 <<
" *.msh -- GMSH ASCII file\n" 675 <<
" *.n -- Sandia's Nemesis format\n" 676 <<
" *.nem -- Sandia's Nemesis format\n" 677 <<
" *.plt -- Tecplot binary file\n" 678 <<
" *.poly -- TetGen ASCII file\n" 679 <<
" *.ucd -- AVS's ASCII UCD format\n" 680 <<
" *.ugrid -- Kelly's DIVA ASCII format\n" 681 <<
" *.unv -- I-deas Universal format\n" 682 <<
" *.vtu -- VTK (paraview-readable) format\n" 683 <<
" *.xda -- libMesh ASCII format\n" 684 <<
" *.xdr -- libMesh binary format,\n" 685 <<
"\n As well as for input only:\n\n" \
686 <<
" *.bext -- Bezier files in DYNA format\n" \
687 <<
" *.bxt -- Bezier files in DYNA format\n" \
688 <<
" *.inp -- Abaqus .inp format\n" \
689 <<
" *.mat -- Matlab triangular ASCII file\n" \
690 <<
" *.off -- OOGL OFF surface format\n" \
691 <<
" *.ogl -- OOGL OFF surface format\n" \
692 <<
" *.oogl -- OOGL OFF surface format\n" \
693 <<
"\n As well as for output only:\n\n" \
694 <<
" *.dat -- Tecplot ASCII file\n" 695 <<
" *.fro -- ACDL's surface triangulation file\n" 696 <<
" *.poly -- TetGen ASCII file\n" std::string name(const ElemQuality q)
This function returns a string containing some name for q.
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false)=0
Interfaces for reading/writing a mesh to/from a file.
virtual unique_id_type parallel_max_unique_id() const =0
virtual Real mean() const
void sync(UnstructuredMesh &boundary_mesh)
Generates boundary_mesh data structures corresponding to the mesh data structures.
Real & desired_volume()
Sets and/or gets the desired tetrahedron volume.
Class NetGenMeshInterface provides an interface for tetrahedralization of meshes using the NetGen lib...
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly ecreated (or read) mesh for use.
const Parallel::Communicator & comm() const
The StatisticsVector class is derived from the std::vector<> and therefore has all of its useful feat...
virtual void triangulate() override
Method invokes NetGen library to compute a tetrahedralization.
Real & desired_volume()
Sets and/or gets the desired element volume.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
The libMesh namespace provides an interface to certain functionality in the library.
virtual void all_first_order()=0
Converts a mesh with higher-order elements into a mesh with linear elements.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
TriangulationType & triangulation_type()
Sets and/or gets the desired triangulation type.
virtual void partition(const unsigned int n_parts)
Call the default partitioner (currently metis_partition()).
A C++ class to refine a simplicial mesh via splitting edges that exceed a given metric.
The BoundaryMesh is a Mesh in its own right, but it contains a description of the boundary of some ot...
std::pair< bool, double > InfElemOriginValue
Useful typedef.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
Real & minimum_angle()
Sets and/or gets the minimum desired angle.
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
bool refine_elements()
Finds elements which exceed the requested metric and refines them via subdivision into new simplices ...
virtual dof_id_type max_elem_id() const =0
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
virtual void histogram(std::vector< dof_id_type > &bin_members, unsigned int n_bins=10)
ElemQuality
Defines an enum for element quality metrics.
virtual void write(const std::string &name) const =0
virtual void triangulate() override
Internally, this calls the poly2tri triangulation code in a loop, inserting our owner Steiner points ...
Real & desired_area()
Sets and/or gets the desired triangle area.
This class is used to build infinite elements on top of an existing mesh.
Triangulate the interior of a Planar Straight Line Graph, which is defined implicitly by the order of...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Point build_inf_elem(const bool be_verbose=false)
Build infinite elements atop a volume-based mesh, determine origin automatically. ...
This is an implementation of Larisa Branets' smoothing algorithms.
virtual std::vector< dof_id_type > cut_below(Real cut) const
virtual const Elem & elem_ref(const dof_id_type i) const
void all_second_order(const bool full_ordered=true)
Calls the range-based version of this function with a range consisting of all elements in the mesh...
unsigned int mesh_dimension() const
A C++ interface between LibMesh and the poly2tri library, with custom code for Steiner point insertio...
virtual std::pair< Real, Real > qual_bounds(const ElemQuality) const
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false) override
Reads the file specified by name.
virtual dof_id_type max_node_id() const =0
void print_summary(std::ostream &out_stream=libMesh::out) const
Prints a summary of the boundary information.
virtual dof_id_type n_elem() const =0
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
virtual void write(const std::string &name) const override
Write the file specified by name.
virtual void smooth() override
Redefinition of the smooth function from the base class.
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.