1 #include <libmesh/boundary_info.h> 2 #include <libmesh/elem.h> 3 #include <libmesh/enum_elem_type.h> 4 #include <libmesh/function_base.h> 5 #include <libmesh/libmesh.h> 6 #include <libmesh/mesh_generation.h> 7 #include <libmesh/mesh_modification.h> 8 #include <libmesh/mesh_smoother_laplace.h> 9 #include <libmesh/mesh_smoother_vsmoother.h> 10 #include <libmesh/mesh_tools.h> 11 #include <libmesh/node.h> 12 #include <libmesh/reference_elem.h> 13 #include <libmesh/replicated_mesh.h> 14 #include <libmesh/mesh.h> 15 #include <libmesh/system.h> 16 #include "libmesh/face_tri.h" 17 #include "libmesh/cell_prism.h" 18 #include "libmesh/utility.h" 19 #include "libmesh/enum_to_string.h" 20 #include "libmesh/parallel_ghost_sync.h" 36 std::unique_ptr<FunctionBase<Real>> clone()
const override 38 return std::make_unique<DistortSquare>();
43 libmesh_not_implemented();
50 const Real eta = 2 * p(0) - 1;
51 const Real zeta = 2 * p(1) - 1;
52 output(0) = p(0) + (pow<3>(eta) - eta) * p(1) * (1 - p(1));
53 output(1) = p(1) + (pow<3>(zeta) - zeta) * p(0) * (1 - p(0));
63 DistortHyperCube(
const unsigned int dim) : _dim(
dim) {}
66 std::unique_ptr<FunctionBase<Real>> clone()
const override 68 return std::make_unique<DistortHyperCube>(_dim);
71 Real operator()(
const Point &,
const Real = 0.)
override { libmesh_not_implemented(); }
79 std::array<bool, 3> is_on_boundary = {
false,
false,
false};
80 for (
unsigned int i = 0; i < _dim; ++i)
82 is_on_boundary[i] =
true;
85 for (
unsigned int i = 0; i < _dim; ++i)
87 if (!is_on_boundary[i])
90 Real modulation = 0.3;
91 Real xi = 2. * p(i) - 1.;
92 for (
unsigned int j = 0; j < _dim; ++j)
96 Real pj = std::clamp(p(j), 0., 1.);
97 modulation *= (pj - 0.5) * (pj - 0.5) * 4.;
100 const auto delta = (pow<3>(xi) - xi) * modulation;
102 output(i) = (delta >
TOLERANCE) ? p(i) + delta : 1.03 * p(i);
109 const unsigned int _dim;
114 std::unique_ptr<FunctionBase<Real>> clone()
const override 116 return std::make_unique<SquareToParallelogram>();
121 libmesh_not_implemented();
130 output(0) = p(0) - 0.5 * p(1);
131 output(1) = 0.5 * std::sqrt(
Real(3)) * p(1);
138 std::unique_ptr<FunctionBase<Real>> clone()
const override 140 return std::make_unique<ParallelogramToSquare>();
145 libmesh_not_implemented();
154 output(0) = p(0) + p(1) / std::sqrt(
Real(3));
155 output(1) = (2. / std::sqrt(
Real(3))) * p(1);
162 std::unique_ptr<FunctionBase<Real>> clone()
const override 164 return std::make_unique<CubeToParallelepiped>();
169 libmesh_not_implemented();
181 output(0) = p(0) + 0.5 * p(1);
182 output(1) = 0.5 * std::sqrt(3) * p(1);
185 output(2) = p(2) * 0.25 * std::sqrt(3.);
191 std::unique_ptr<FunctionBase<Real>> clone()
const override 193 return std::make_unique<ParallelepipedToCube>();
198 libmesh_not_implemented();
210 output(0) = p(0) - p(1) / std::sqrt(3.);
211 output(1) = (2. / std::sqrt(3)) * p(1);
214 output(2) = p(2) * 4. / std::sqrt(3.);
231 CPPUNIT_TEST(testLaplaceQuad);
232 CPPUNIT_TEST(testLaplaceTri);
233 #if defined(LIBMESH_ENABLE_VSMOOTHER) && defined(LIBMESH_HAVE_SOLVER) 234 CPPUNIT_TEST(testVariationalEdge2);
235 CPPUNIT_TEST(testVariationalEdge3);
236 CPPUNIT_TEST(testVariationalEdge3MultipleSubdomains);
238 CPPUNIT_TEST(testVariationalQuad4);
239 CPPUNIT_TEST(testVariationalQuad4MultipleSubdomains);
240 CPPUNIT_TEST(testVariationalQuad8);
241 CPPUNIT_TEST(testVariationalQuad9);
242 CPPUNIT_TEST(testVariationalQuad9MultipleSubdomains);
243 CPPUNIT_TEST(testVariationalQuad4Tangled);
245 CPPUNIT_TEST(testVariationalTri3);
246 CPPUNIT_TEST(testVariationalTri6);
247 CPPUNIT_TEST(testVariationalTri6MultipleSubdomains);
249 CPPUNIT_TEST(testVariationalHex8);
250 CPPUNIT_TEST(testVariationalHex20);
251 CPPUNIT_TEST(testVariationalHex27);
252 CPPUNIT_TEST(testVariationalHex27Tangled);
253 CPPUNIT_TEST(testVariationalHex27MultipleSubdomains);
255 CPPUNIT_TEST(testVariationalPyramid5);
256 CPPUNIT_TEST(testVariationalPyramid13);
257 CPPUNIT_TEST(testVariationalPyramid14);
258 CPPUNIT_TEST(testVariationalPyramid18);
259 CPPUNIT_TEST(testVariationalPyramid18MultipleSubdomains);
261 CPPUNIT_TEST(testVariationalPrism6);
262 CPPUNIT_TEST(testVariationalPrism15);
263 CPPUNIT_TEST(testVariationalPrism18);
264 CPPUNIT_TEST(testVariationalPrism20);
265 CPPUNIT_TEST(testVariationalPrism21);
266 CPPUNIT_TEST(testVariationalPrism21MultipleSubdomains);
268 CPPUNIT_TEST(testVariationalTet4);
269 CPPUNIT_TEST(testVariationalTet10);
270 CPPUNIT_TEST(testVariationalTet14);
271 CPPUNIT_TEST(testVariationalTet14MultipleSubdomains);
273 #if defined(LIBMESH_HAVE_GZSTREAM) 274 CPPUNIT_TEST(testVariationalMixed2D);
275 CPPUNIT_TEST(testVariationalMixed3D);
278 #endif // LIBMESH_ENABLE_VSMOOTHER 281 CPPUNIT_TEST_SUITE_END();
292 constexpr
unsigned int n_elems_per_side = 4;
295 mesh, n_elems_per_side, n_elems_per_side, 0., 1., 0., 1., type);
302 auto center_distortion_is =
304 const Real r = node(d);
305 const Real R = r * n_elems_per_side;
313 const Real R1 = node(1) * n_elems_per_side;
321 const Real R0 = node(0) * n_elems_per_side;
331 return ((std::abs(R - std::round(R)) > distortion_tol) == distortion);
334 for (
auto node :
mesh.node_ptr_range())
336 CPPUNIT_ASSERT(center_distortion_is(*node, 0,
true));
337 CPPUNIT_ASSERT(center_distortion_is(*node, 1,
true));
343 for (
unsigned int i = 0; i != 8; ++i)
347 for (
auto node :
mesh.node_ptr_range())
349 CPPUNIT_ASSERT(center_distortion_is(*node, 0,
false, 1e-3));
350 CPPUNIT_ASSERT(center_distortion_is(*node, 1,
false, 1e-3));
356 std::pair<unsigned int, unsigned int>
359 const auto half_length = 0.5 * side_length;
360 unsigned int num_centered = 0;
361 unsigned int num_face = 0;
364 const auto num_half_lengths = point(d) / half_length;
365 if (std::abs(num_half_lengths - std::round(num_half_lengths)) > tol)
369 if (std::lround(num_half_lengths) % 2)
377 return std::make_pair(num_centered, num_face);
384 return numCenteredAndFacedDimensions(point, side_length, tol).first == 3;
391 return numCenteredAndFacedDimensions(point, side_length, tol).second == 3;
398 const auto result = numCenteredAndFacedDimensions(point, side_length, tol);
399 return (result.first == 2) && (result.second == 1);
405 const bool multiple_subdomains =
false,
406 const bool tangle_mesh =
false,
407 const Real tangle_damping_factor = 1.0)
411 if (multiple_subdomains && tangle_mesh)
412 libmesh_not_implemented_msg(
413 "Arbitrary mesh tangling with multiple subdomains is not supported.");
417 const auto dim = ref_elem->dim();
426 const auto side_length = 1.0 / n_elems_per_side;
435 mesh, n_elems_per_side, n_elems_per_side, 0., 1., 0., 1., type);
453 libmesh_error_msg(
"Unsupported dimension " <<
dim);
457 DistortHyperCube dh(
dim);
480 std::map<dof_id_type, Real> dist1_map;
482 std::map<dof_id_type, Real> dist2_map;
484 for (
const auto * node :
mesh.local_node_ptr_range())
486 dist1_map[node->id()] = (*node - p1).
norm();
487 dist2_map[node->id()] = (*node - p2).
norm();
493 auto get_closet_point_accross_all_procs =
494 [&
mesh, &proc_id](
const std::map<dof_id_type, Real> &dist_map) {
497 Real d_min_local = std::numeric_limits<Real>::max();
506 std::min_element(dist_map.begin(), dist_map.end(),
507 [](
const auto &a,
const auto &
b) {
508 return a.second <
b.second;
511 node_id = min_it->first;
512 d_min_local = min_it->second;
516 auto d_min_global = d_min_local;
522 if (d_min_local == d_min_global) {
523 broadcasting_proc = proc_id;
532 return std::pair(node_id, node);
535 const auto [node_id1, node1] =
536 get_closet_point_accross_all_procs(dist1_map);
537 const auto [node_id2, node2] =
538 get_closet_point_accross_all_procs(dist2_map);
541 const auto displacement = tangle_damping_factor * (node1 - node2);
549 mesh.nodes_end(), sync_object);
555 CPPUNIT_ASSERT(unsmoothed_info.mesh_is_tangled);
559 std::unordered_map<subdomain_id_type, Real> distorted_subdomain_volumes;
561 if (multiple_subdomains)
564 for (
auto * elem :
mesh.active_element_ptr_range())
566 unsigned int subdomain_id = 0;
568 if (elem->vertex_average()(d) > 0.5)
570 elem->subdomain_id() += subdomain_id;
576 for (
auto *elem :
mesh.active_element_ptr_range()) {
577 const auto sub_id = elem->subdomain_id();
579 if (elem->processor_id() != proc_id)
581 distorted_subdomain_volumes[sub_id] += elem->volume();
582 highest_subdomain_id = std::max(sub_id, highest_subdomain_id);
587 for (
const auto sub_id :
make_range(highest_subdomain_id + 1)) {
589 if (distorted_subdomain_volumes.find(sub_id) ==
590 distorted_subdomain_volumes.end())
591 distorted_subdomain_volumes[sub_id] = 0.;
593 mesh.
comm().
sum(distorted_subdomain_volumes[sub_id]);
603 libmesh_error_msg_if(elem_orders.size() != 1,
604 "The variational smoother cannot be used for mixed-order meshes!");
609 const auto scale_factor = *elem_orders.begin() * ((type_is_pyramid || type_is_tet) ? 2 * 4 : 1);
612 auto node_distortion_is = [&n_elems_per_side, &
dim, &boundary_info, &scale_factor, &type_is_prism](
615 std::vector<boundary_id_type> boundary_ids;
616 boundary_info.boundary_ids(&node, boundary_ids);
619 const auto num_dofs =
dim - boundary_ids.size();
639 std::size_t num_zero_or_one = 0;
641 bool distorted =
false;
644 const Real r = node(d);
645 const Real R = r * n_elems_per_side * scale_factor;
646 CPPUNIT_ASSERT_GREATER(-distortion_tol * distortion_tol, r);
647 CPPUNIT_ASSERT_GREATER(-distortion_tol * distortion_tol, 1 - r);
649 bool d_distorted = std::abs(R - std::round(R)) > distortion_tol;
650 if (type_is_prism && (scale_factor == 3))
655 const Real R_prism = R / scale_factor * 2;
656 const bool d_distorted_prism =
657 std::abs(R_prism - std::round(R_prism)) > distortion_tol;
658 d_distorted &= d_distorted_prism;
660 distorted |= d_distorted;
664 CPPUNIT_ASSERT_GREATEREQUAL(
dim - num_dofs, num_zero_or_one);
670 return distorted == distortion;
674 for (
auto node :
mesh.node_ptr_range())
675 CPPUNIT_ASSERT(node_distortion_is(*node,
true));
685 SquareToParallelogram stp;
688 else if (type_is_prism)
693 CubeToParallelepiped ctp;
704 ParallelogramToSquare pts;
707 else if (type_is_prism)
712 ParallelepipedToCube ptc;
716 if (multiple_subdomains)
721 std::unordered_map<subdomain_id_type, Real> smoothed_subdomain_volumes;
722 for (
auto *elem :
mesh.active_element_ptr_range()) {
724 if (elem->processor_id() != proc_id)
726 smoothed_subdomain_volumes[elem->subdomain_id()] += elem->volume();
730 for (
const auto sub_id :
make_range(highest_subdomain_id + 1)) {
732 if (smoothed_subdomain_volumes.find(sub_id) ==
733 smoothed_subdomain_volumes.end())
734 smoothed_subdomain_volumes[sub_id] = 0.;
736 mesh.
comm().
sum(smoothed_subdomain_volumes[sub_id]);
739 for (
const auto sub_id :
make_range(highest_subdomain_id + 1))
741 libmesh_map_find(distorted_subdomain_volumes, sub_id),
742 libmesh_map_find(smoothed_subdomain_volumes, sub_id),
TOLERANCE));
746 std::unordered_map<dof_id_type, std::vector<const Elem *>> nodes_to_elem_map;
751 std::set<dof_id_type> nodes_checked;
754 for (
const auto * elem :
mesh.active_element_ptr_range())
756 for (
const auto local_node_id :
make_range(elem->n_nodes()))
758 const auto & node = elem->node_ref(local_node_id);
759 if (nodes_checked.find(node.id()) != nodes_checked.end())
762 nodes_checked.insert(node.id());
768 if (local_node_id > 8 && local_node_id < 13)
780 const auto & base = elem->node_ref(local_node_id - 9);
781 const auto & apex = elem->node_ref(4);
782 const Real x = (type ==
PYRAMID18) ? 0.56646084 : 0.54985875;
784 CPPUNIT_ASSERT(node.absolute_fuzzy_equals(base + x * (apex - base), tol));
787 else if (local_node_id > 13)
797 const auto & base1 = elem->node_ref(local_node_id - 14);
798 const auto & base2 = elem->node_ref((local_node_id - 13) % 4);
799 const auto & apex = elem->node_ref(4);
801 const auto node_approx =
802 (0.31401599 * base1 + 0.31401599 * base2 + 0.37196802 * apex);
803 CPPUNIT_ASSERT(node.absolute_fuzzy_equals(node_approx, tol));
810 else if (type_is_tet && !elem->is_vertex(local_node_id))
815 std::vector<const Node *> neighbors;
817 mesh, node, nodes_to_elem_map, neighbors);
819 switch (neighbors.size())
826 const auto is_0_cube_center =
827 pointIsCubeCenter(*neighbors[0], side_length);
828 const auto is_1_cube_center =
829 pointIsCubeCenter(*neighbors[1], side_length);
832 if (is_0_cube_center || is_1_cube_center)
834 const auto & cube_center =
835 is_0_cube_center ? *neighbors[0] : *neighbors[1];
837 is_0_cube_center ? *neighbors[1] : *neighbors[0];
842 if (pointIsCubeFaceCenter(other, side_length))
844 const Real x = (type ==
TET10) ? 0.42895041 : 0.41486385;
845 CPPUNIT_ASSERT(node.absolute_fuzzy_equals(
846 other + x * (cube_center - other), tol));
849 else if (pointIsCubeVertex(other, side_length))
851 const Real x = (type ==
TET10) ? 0.55388920 : 0.58093516;
852 CPPUNIT_ASSERT(node.absolute_fuzzy_equals(
853 other + x * (cube_center - other), tol));
862 const auto is_0_cube_vertex =
863 pointIsCubeVertex(*neighbors[0], side_length);
864 const auto is_1_cube_vertex =
865 pointIsCubeVertex(*neighbors[1], side_length);
866 const auto is_0_cube_face_center =
867 pointIsCubeFaceCenter(*neighbors[0], side_length);
868 const auto is_1_cube_face_center =
869 pointIsCubeFaceCenter(*neighbors[1], side_length);
871 if (is_0_cube_vertex && is_1_cube_vertex)
875 CPPUNIT_ASSERT(node_distortion_is(node,
false));
879 libmesh_error_msg_if(
880 (is_0_cube_center || is_0_cube_face_center) &&
881 (is_1_cube_center || is_1_cube_face_center),
882 "We should never get here!");
883 const auto & cube_vertex =
884 is_0_cube_vertex ? *neighbors[0] : *neighbors[1];
885 const auto & cube_face_center =
886 is_0_cube_face_center ? *neighbors[0] : *neighbors[1];
887 const Real x = (type ==
TET10) ? 0.61299101 : 0.65125580;
888 CPPUNIT_ASSERT(node.absolute_fuzzy_equals(
889 cube_vertex + x * (cube_face_center - cube_vertex), tol));
900 neighbors.erase(std::remove_if(neighbors.begin(),
902 [&elem](
const Node * n) {
903 return !elem->is_vertex(
904 elem->local_node(n->id()));
921 unsigned int num_vertices_at_cube_center = 0;
922 unsigned int num_vertices_at_cube_vertices = 0;
923 unsigned int num_vertices_at_cube_face_centers = 0;
924 for (
const auto * neighbor : neighbors)
926 if (pointIsCubeCenter(*neighbor, side_length))
927 num_vertices_at_cube_center += 1;
928 else if (pointIsCubeVertex(*neighbor, side_length))
929 num_vertices_at_cube_vertices += 1;
930 else if (pointIsCubeFaceCenter(*neighbor, side_length))
931 num_vertices_at_cube_face_centers += 1;
939 if (num_vertices_at_cube_vertices == 2)
942 if (num_vertices_at_cube_center)
943 for (
const auto * neighbor : neighbors)
946 if (pointIsCubeVertex(*neighbor, side_length))
948 else if (pointIsCubeCenter(*neighbor, side_length))
951 libmesh_error_msg(
"We should never get here!");
953 node_approx +=
weight * (*neighbor);
957 else if (num_vertices_at_cube_face_centers)
958 for (
const auto * neighbor : neighbors)
961 if (pointIsCubeVertex(*neighbor, side_length))
963 else if (pointIsCubeFaceCenter(*neighbor, side_length))
966 libmesh_error_msg(
"We should never get here!");
968 node_approx +=
weight * (*neighbor);
972 libmesh_error_msg(
"We should never get here!");
976 else if (num_vertices_at_cube_center && num_vertices_at_cube_vertices &&
977 num_vertices_at_cube_face_centers)
978 for (
const auto * neighbor : neighbors)
981 if (pointIsCubeCenter(*neighbor, side_length))
983 else if (pointIsCubeVertex(*neighbor, side_length))
985 else if (pointIsCubeFaceCenter(*neighbor, side_length))
988 libmesh_error_msg(
"We should never get here!");
990 node_approx +=
weight * (*neighbor);
994 libmesh_error_msg(
"We should never get here!");
996 CPPUNIT_ASSERT(node.absolute_fuzzy_equals(node_approx, tol));
1002 libmesh_error_msg(node <<
" has unexpected number of neighbors (" 1003 << neighbors.size() <<
")");
1009 CPPUNIT_ASSERT(node_distortion_is(node,
false));
1030 const bool distortion,
1036 const auto & gold_node = gold_mesh.
node_ref(node_id);
1040 const bool d_distorted = std::abs(gold_node(d) - node(d)) > distortion_tol;
1052 CPPUNIT_ASSERT(mesh_distortion_is(gold_mesh,
mesh,
true));
1063 CPPUNIT_ASSERT(mesh_distortion_is(gold_mesh,
mesh,
false));
1071 testLaplaceSmoother(
mesh, laplace,
QUAD4);
1079 testLaplaceSmoother(
mesh, laplace,
TRI3);
1082 #ifdef LIBMESH_ENABLE_VSMOOTHER 1088 testVariationalSmoother(
mesh, variational,
EDGE2);
1096 testVariationalSmoother(
mesh, variational,
EDGE3);
1104 testVariationalSmoother(
mesh, variational,
EDGE3,
true);
1117 testVariationalSmoother(
mesh, variational,
QUAD4);
1128 testVariationalSmoother(
mesh, variational,
QUAD4,
true);
1136 testVariationalSmoother(
mesh, variational,
QUAD8);
1144 testVariationalSmoother(
mesh, variational,
QUAD9);
1152 testVariationalSmoother(
mesh, variational,
QUAD9,
true);
1160 testVariationalSmoother(
mesh, variational,
QUAD4,
false,
true, 0.65);
1168 testVariationalSmoother(
mesh, variational,
TRI3);
1176 testVariationalSmoother(
mesh, variational,
TRI6);
1184 testVariationalSmoother(
mesh, variational,
TRI3,
true);
1192 testVariationalSmoother(
mesh, variational,
HEX8);
1200 testVariationalSmoother(
mesh, variational,
HEX20);
1208 testVariationalSmoother(
mesh, variational,
HEX27);
1216 testVariationalSmoother(
mesh, variational,
HEX27,
true);
1224 testVariationalSmoother(
mesh, variational,
HEX27,
false,
true, 0.55);
1264 testVariationalSmoother(
mesh, variational,
PYRAMID18,
true);
1272 testVariationalSmoother(
mesh, variational,
PRISM6);
1280 testVariationalSmoother(
mesh, variational,
PRISM15);
1289 testVariationalSmoother(
mesh, variational,
PRISM18);
1298 testVariationalSmoother(
mesh, variational,
PRISM20);
1307 testVariationalSmoother(
mesh, variational,
PRISM21);
1316 testVariationalSmoother(
mesh, variational,
PRISM21,
true);
1329 testVariationalSmoother(
mesh, variational,
TET4);
1340 testVariationalSmoother(
mesh, variational,
TET10);
1348 testVariationalSmoother(
mesh, variational,
TET14);
1356 testVariationalSmoother(
mesh, variational,
TET14,
true);
1362 mesh.
read(
"meshes/quad4_tri3_smoothed.xda.gz");
1364 testVariationalSmootherRegression(
mesh);
1370 mesh.
read(
"meshes/hex8_prism6_smoothed.xda.gz");
1372 testVariationalSmootherRegression(
mesh);
1375 #endif // LIBMESH_ENABLE_VSMOOTHER virtual dof_id_type n_nodes() const override final
void testVariationalHex27Tangled()
void testVariationalQuad8()
static const Order type_to_default_order_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the default approximation order of...
std::pair< unsigned int, unsigned int > numCenteredAndFacedDimensions(const Point &point, const Real &side_length, const Real &tol)
ElemType
Defines an enum for geometric element types.
const std::set< Order > & elem_default_orders() const
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
A Node is like a Point, but with more information.
virtual void zero() override final
Set every element in the vector to 0.
void testVariationalTri3()
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.
void testLaplaceSmoother(ReplicatedMesh &mesh, MeshSmoother &smoother, ElemType type)
void testVariationalPrism18()
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
libMesh::Parallel::Communicator * TestCommWorld
static constexpr Real TOLERANCE
virtual void smooth() override
Redefinition of the smooth function from the base class.
void resize(const unsigned int n)
Resize the vector.
void testVariationalQuad4()
const MeshQualityInfo & get_mesh_info() const
Getter for the _system's _mesh_info attribute.
bool pointIsCubeVertex(const Point &point, const Real &side_length, const Real &tol=TOLERANCE)
void testVariationalEdge2()
void testVariationalPyramid18MultipleSubdomains()
const Parallel::Communicator & comm() const
void testVariationalPrism21MultipleSubdomains()
void testVariationalMixed2D()
void testVariationalSmoother(Mesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
virtual void smooth()=0
Function which actually performs the smoothing operations.
void testVariationalHex27()
uint8_t processor_id_type
This class defines the data structures necessary for Laplace smoothing.
void testVariationalEdge3()
void testVariationalTet14()
void min(const T &r, T &o, Request &req) const
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
void testVariationalPrism21()
bool pointIsCubeFaceCenter(const Point &point, const Real &side_length, const Real &tol=TOLERANCE)
void testVariationalQuad4Tangled()
void testVariationalPyramid5()
virtual const Node * query_node_ptr(const dof_id_type i) const =0
void testVariationalHex8()
void testVariationalQuad9()
void testVariationalQuad9MultipleSubdomains()
CPPUNIT_TEST_SUITE_REGISTRATION(MeshSmootherTest)
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
streambufT * rdbuf() const
Get the associated stream buffer.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
void testVariationalPrism6()
std::string enum_to_string(const T e)
void testVariationalTet4()
void testVariationalHex20()
void testVariationalTet14MultipleSubdomains()
bool absolute_fuzzy_equals(const T &var1, const T2 &var2, const Real tol=TOLERANCE *TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
void testVariationalHex27MultipleSubdomains()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void testVariationalPrism20()
void testVariationalSmootherRegression(const ReplicatedMesh &gold_mesh)
void testVariationalPyramid14()
This is an implementation of Larisa Branets' smoothing algorithms.
void max(const T &r, T &o, Request &req) const
void testVariationalPrism15()
void testVariationalTri6MultipleSubdomains()
void testVariationalMixed3D()
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...
unsigned int mesh_dimension() const
void testVariationalPyramid18()
void testVariationalTet10()
void testVariationalTri6()
void testVariationalPyramid13()
virtual const Node & node_ref(const dof_id_type i) const
bool pointIsCubeCenter(const Point &point, const Real &side_length, const Real &tol=TOLERANCE)
This class provides the necessary interface for mesh smoothing.
bool relative_fuzzy_equals(const T &var1, const T2 &var2, const Real tol=TOLERANCE *TOLERANCE)
Function to check whether two variables are equal within a relative tolerance.
Defines a dense vector for use in Finite Element-type computations.
virtual void setup()
Setup method that creates equation systems, system, and constraints, to be called just prior to smoot...
void testVariationalQuad4MultipleSubdomains()
Base class for functors that can be evaluated at a point and (optionally) time.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
const Elem & get(const ElemType type_in)
virtual dof_id_type n_nodes() const =0
void testVariationalEdge3MultipleSubdomains()