62{
64
65 unsigned int n_subdomains = 1;
66 bool vsmooth = false;
67 unsigned int n_rsteps = 0;
68 Real simplex_refine = 0.;
69 double dist_fact = 0.;
70 bool verbose = false;
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;
79
80#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
81 bool addinfelems = false;
85 bool x_sym=false;
86 bool y_sym=false;
87 bool z_sym=false;
88#endif
89
90 std::vector<std::string> names;
91 std::vector<std::string> output_names;
92
93
94 if (argc < 3)
95 usage(std::string(argv[0]));
96
97
98 GetPot command_line (argc, argv);
99
100
101 if (command_line.search(2, "-h", "-?"))
103
104
105 command_line.disable_loop();
106 while (command_line.search(1, "-i"))
107 {
108 std::string tmp;
109 tmp = command_line.next(tmp);
110 names.push_back(tmp);
111 }
112 command_line.reset_cursor();
113
114
115 while (command_line.search(1, "-o"))
116 {
117 std::string tmp;
118 tmp = command_line.next(tmp);
119 output_names.push_back(tmp);
120 }
121 command_line.enable_loop();
122
123
124 if (command_line.search(1, "-D"))
125 dist_fact = command_line.next(dist_fact);
126
127
128 if (command_line.search(1, "-r"))
129 {
130 int tmp = 0;
131 tmp = command_line.next(tmp);
132 n_rsteps = cast_int<unsigned int>(tmp);
133 }
134
135
136 if (command_line.search(1, "-s"))
137 simplex_refine = command_line.next(simplex_refine);
138
139
140 if (command_line.search(1, "-p"))
141 {
142 int tmp = 0;
143 tmp = command_line.next(tmp);
144 n_subdomains = cast_int<unsigned int>(tmp);
145 }
146
147
148 if (command_line.search(1, "-V"))
149 vsmooth = true;
150
151
152 if (command_line.search(1, "-t"))
153 triangulate = true;
154
155
156 if (command_line.search(1, "-T"))
157 {
158 simplex_fill = true;
159 desired_measure = command_line.next(desired_measure);
160 }
161
162
163 if (command_line.search(1, "-q"))
164 {
165 do_quality = true;
166 std::string tmp;
167 tmp = command_line.next(tmp);
168 if (tmp != "")
169 quality_type = Utility::string_to_enum<ElemQuality>(tmp);
170 }
171
172
173 if (command_line.search(1, "-v"))
174 verbose = true;
175
176
177 if (command_line.search(1, "-b"))
179
180
181 if (command_line.search(1, "-1"))
182 convert_first_order = true;
183
184
185 if (command_line.search(1, "-2"))
186 convert_second_order = 2;
187
188
189 if (command_line.search(1, "-3"))
190 convert_second_order = 22;
191
192#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
193
194
195 if (command_line.search(1, "-a"))
196 addinfelems = true;
197
198
199 if (command_line.search(1, "-x"))
200 {
201 origin_x.first = true;
202 origin_x.second = command_line.next(origin_x.second);
203 }
204
205
206 if (command_line.search(1, "-y"))
207 {
208 origin_y.first = true;
209 origin_y.second = command_line.next(origin_y.second);
210 }
211
212
213 if (command_line.search(1, "-z"))
214 {
215 origin_z.first = true;
216 origin_z.second = command_line.next(origin_z.second);
217 }
218
219
220 if (command_line.search(1, "-X"))
221 x_sym = true;
222 if (command_line.search(1, "-Y"))
223 y_sym = true;
224 if (command_line.search(1, "-Z"))
225 z_sym = true;
226
227#endif
228
229
231 if (!names.empty())
232 {
234
235 if (verbose)
236 {
237 libMesh::out <<
"Mesh " << names[0] <<
":" << std::endl;
240 }
241
242 for (unsigned int i=1; i < names.size(); ++i)
243 {
245 extra_mesh.read(names[i]);
246
247 if (verbose)
248 {
249 libMesh::out <<
"Mesh " << names[i] <<
":" << std::endl;
250 extra_mesh.print_info();
251 extra_mesh.get_boundary_info().print_summary();
252 }
253
255#ifdef LIBMESH_ENABLE_UNIQUE_ID
257#endif
258
259 mesh.copy_nodes_and_elements(extra_mesh,
false,
262 max_uid);
264
265 if (verbose)
266 {
270 }
271 }
272 }
273
274 else
275 {
277 return 1;
278 }
279
280
281
282#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
283
284 if (addinfelems)
285 {
287 "ERROR: Invalid combination: Building infinite elements\n"
288 "not compatible with writing boundary conditions.");
289
290
291
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.");
298
299
301 x_sym, y_sym, z_sym,
302 verbose);
303
304 if (verbose)
305 {
308 }
309 }
310
311
312 else
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!");
317
318#endif
319
320
321
322 if (triangulate)
323 {
324 if (verbose)
326
328 }
329
330
331 if (simplex_fill)
332 {
334 {
335#ifdef LIBMESH_HAVE_NETGEN
337 ngint.desired_volume() = desired_measure;
338 ngint.triangulate();
339#else
340 libmesh_error_msg("Requested triangulation of a 2D boundary without Poly2Tri enabled");
341#endif
342 }
344 {
345#ifdef LIBMESH_HAVE_POLY2TRI
348 poly2tri.desired_area() = desired_measure;
349 poly2tri.minimum_angle() = 0;
350 poly2tri.triangulate();
351#else
352 libmesh_error_msg("Requested triangulation of a 1D boundary without Poly2Tri enabled");
353#endif
354 }
355 }
356
357
358 if (do_quality)
359 {
362
364
365
367 libMesh::out <<
"Quality bounds for this element type are: ("
368 << bounds.first
369 << ", "
370 << bounds.second
371 << ") "
372 << std::endl;
373
374 for (
const auto & elem :
mesh.active_element_ptr_range())
375 sv.push_back(elem->quality(quality_type));
376
377 const unsigned int n_bins = 10;
379
380
381
382 std::vector<dof_id_type> bad_elts = sv.
cut_below(0.8);
385 << " elements below the cutoff." << std::endl;
386
387
388 std::vector<dof_id_type> histogram;
390
391 const bool do_matlab = true;
392
393 if (do_matlab)
394 {
395 std::ofstream
out (
"histo.m");
396
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++)
401 << std::endl;
402 out <<
"];" << std::endl;
403
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 ;
410
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;
415
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;
422
424
425 }
426 }
427
428
429
430 if (convert_first_order)
431 {
432 if (verbose)
433 libMesh::out <<
"Converting elements to first order counterparts\n";
434
436
437 if (verbose)
438 {
441 }
442 }
443
444
445 if (convert_second_order > 0)
446 {
447 bool second_order_mode = true;
448 std:: string message = "Converting elements to second order counterparts";
449 if (convert_second_order == 2)
450 {
451 second_order_mode = false;
452 message += ", lower version: Quad4 -> Quad8, not Quad9";
453 }
454
455 else if (convert_second_order == 22)
456 {
457 second_order_mode = true;
458 message += ", highest version: Quad4 -> Quad9";
459 }
460
461 else
462 libmesh_error_msg("Invalid value, convert_second_order = " << convert_second_order);
463
464 if (verbose)
466
468
469 if (verbose)
470 {
473 }
474 }
475
476 if (simplex_refine)
477 {
479 simplex_refiner.desired_volume() = simplex_refine;
480 simplex_refiner.refine_elements();
481 }
482
483#ifdef LIBMESH_ENABLE_AMR
484
485
486 if (n_rsteps > 0)
487 {
488 if (verbose)
490 << n_rsteps << " times"
491 << std::endl;
492
494 mesh_refinement.uniformly_refine(n_rsteps);
495
496 if (verbose)
497 {
500 }
501 }
502
503
504
505 if (dist_fact > 0.)
506 {
508 << dist_fact
509 << std::endl;
510
512 }
513
514#endif
515
516
517
518
519 if (n_subdomains > 1)
521
522
523 if (vsmooth)
524 {
526 vsmoother.smooth();
527 }
528
529
530 if (output_names.size())
531 {
532
533
534
535
536
537
538 if (n_rsteps > 0)
539 {
540 if (verbose)
541 libMesh::out <<
" Mesh got refined, will write only _active_ elements." << std::endl;
542
544
546 (new_mesh,
547 mesh.active_elements_begin(),
548 mesh.active_elements_end());
549
550
551 for (auto & output_name : output_names)
552 new_mesh.write(output_name);
553 }
554 else
555 {
556
557 for (auto & output_name : output_names)
558 mesh.write(output_name);
559 }
560
561
562
563
565 {
568
571
572 else
573 libmesh_error_msg("Invalid value write_bndry = " << write_bndry);
574
575
576 for (auto boundary_name : output_names)
577 {
578 boundary_name = "bndry_" + boundary_name;
579 boundary_mesh.write(boundary_name);
580 }
581 }
582 }
583
584 return 0;
585}
void sync(UnstructuredMesh &boundary_mesh)
Generates boundary_mesh data structures corresponding to the mesh data structures.
void print_summary(std::ostream &out_stream=libMesh::out) const
Prints a summary of the boundary information.
The BoundaryMesh is a Mesh in its own right, but it contains a description of the boundary of some ot...
virtual std::pair< Real, Real > qual_bounds(const ElemQuality) const
This class is used to build infinite elements on top of an existing mesh.
const Point build_inf_elem(const bool be_verbose=false)
Build infinite elements atop a volume-based mesh, determine origin automatically.
std::pair< bool, double > InfElemOriginValue
Useful typedef.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
unsigned int mesh_dimension() const
virtual dof_id_type n_elem() const =0
virtual void all_first_order()=0
Converts a mesh with higher-order elements into a mesh with linear elements.
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.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false, bool skip_detect_interior_parents=false)=0
Interfaces for reading/writing a mesh to/from a file.
virtual dof_id_type max_node_id() const =0
virtual dof_id_type max_elem_id() const =0
virtual const Elem & elem_ref(const dof_id_type i) const
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
virtual void partition(const unsigned int n_parts)
Call the default partitioner (currently metis_partition()).
virtual unique_id_type parallel_max_unique_id() const =0
Implements (adaptive) mesh refinement algorithms for a MeshBase.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Class NetGenMeshInterface provides an interface for tetrahedralization of meshes using the NetGen lib...
const Parallel::Communicator & comm() const
A C++ interface between LibMesh and the poly2tri library, with custom code for Steiner point insertio...
A C++ class to refine a simplicial mesh via splitting edges that exceed a given metric.
The StatisticsVector class is derived from the std::vector<> and therefore has all of its useful feat...
virtual Real mean() const
virtual std::vector< dof_id_type > cut_below(Real cut) const
virtual void histogram(std::vector< dof_id_type > &bin_members, unsigned int n_bins=10)
@ PSLG
Triangulate the interior of a Planar Straight Line Graph, which is defined implicitly by the order of...
This is an implementation of Larisa Branets' smoothing algorithms.
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
ElemQuality
Defines an enum for element quality metrics.
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real