1 #include <libmesh/libmesh.h> 2 #include <libmesh/enum_elem_type.h> 3 #include <libmesh/function_base.h> 4 #include <libmesh/mesh_generation.h> 5 #include <libmesh/mesh_modification.h> 6 #include <libmesh/mesh_smoother_laplace.h> 7 #include <libmesh/mesh_smoother_vsmoother.h> 8 #include <libmesh/mesh_tools.h> 9 #include <libmesh/node.h> 10 #include <libmesh/elem.h> 11 #include <libmesh/replicated_mesh.h> 12 #include <libmesh/boundary_info.h> 13 #include <libmesh/system.h> 23 std::unique_ptr<FunctionBase<Real>> clone ()
const override 24 {
return std::make_unique<DistortSquare>(); }
27 const Real = 0.)
override 28 { libmesh_not_implemented(); }
31 void operator() (
const Point & p,
36 const Real eta = 2*p(0)-1;
37 const Real zeta = 2*p(1)-1;
38 output(0) = p(0) + (
std::pow(eta,3)-eta)*p(1)*(1-p(1));
39 output(1) = p(1) + (
std::pow(zeta,3)-zeta)*p(0)*(1-p(0));
46 std::unique_ptr<FunctionBase<Real>> clone ()
const override 47 {
return std::make_unique<SquareToParallelogram>(); }
50 const Real = 0.)
override 51 { libmesh_not_implemented(); }
56 void operator() (
const Point & p,
61 output(0) = p(0) - 0.5 * p(1);
62 output(1) = 0.5 * std::sqrt(3) * p(1);
69 std::unique_ptr<FunctionBase<Real>> clone ()
const override 70 {
return std::make_unique<ParallelogramToSquare>(); }
73 const Real = 0.)
override 74 { libmesh_not_implemented(); }
79 void operator() (
const Point & p,
84 output(0) = p(0) + p(1) / std::sqrt(3.);
85 output(1) = (2. / std::sqrt(3)) * p(1);
104 CPPUNIT_TEST( testLaplaceQuad );
105 CPPUNIT_TEST( testLaplaceTri );
106 #if defined(LIBMESH_ENABLE_VSMOOTHER) && defined(LIBMESH_HAVE_SOLVER) 107 CPPUNIT_TEST( testVariationalQuad );
108 CPPUNIT_TEST( testVariationalTri );
109 CPPUNIT_TEST( testVariationalQuadMultipleSubdomains );
110 # endif // LIBMESH_ENABLE_VSMOOTHER 113 CPPUNIT_TEST_SUITE_END();
124 unsigned int n_elems_per_side = 4;
133 std::unordered_map<dof_id_type, Point> subdomain_boundary_node_id_to_point;
134 if (multiple_subdomains)
137 for (
auto * elem :
mesh.active_element_ptr_range())
138 if (elem->vertex_average()(0) > 0.5)
139 ++elem->subdomain_id();
144 for (
auto * elem :
mesh.active_element_ptr_range())
145 for (
const auto & s : elem->side_index_range())
147 const auto* neighbor = elem->neighbor_ptr(s);
148 if (neighbor ==
nullptr)
151 if (elem->subdomain_id() != neighbor->subdomain_id())
154 for (
const auto & n : elem->nodes_on_side(s))
155 subdomain_boundary_node_id_to_point[elem->node_id(n)] =
Point(*(elem->get_nodes()[n]));
162 auto center_distortion_is = [&boundary_info, n_elems_per_side]
163 (
const Node & node,
int d,
bool distortion,
165 const Real r = node(d);
166 const Real R = r * n_elems_per_side;
167 CPPUNIT_ASSERT_GREATER(-distortion_tol*distortion_tol, r);
168 CPPUNIT_ASSERT_GREATER(-distortion_tol*distortion_tol, 1-r);
171 if (std::abs(r-0.5) < distortion_tol*distortion_tol)
178 std::vector<boundary_id_type> boundary_ids;
179 boundary_info.boundary_ids(&node, boundary_ids);
181 switch (boundary_ids.size())
185 return ((std::abs(R-std::round(R)) > distortion_tol) == distortion);
196 if (std::abs(node(0)) < distortion_tol*distortion_tol ||
197 std::abs(node(0)-1) < distortion_tol*distortion_tol)
199 const Real R1 = node(1) * n_elems_per_side;
200 CPPUNIT_ASSERT_LESS(distortion_tol*distortion_tol, std::abs(R1-std::round(R1)));
204 if (std::abs(node(1)) < distortion_tol*distortion_tol ||
205 std::abs(node(1)-1) < distortion_tol*distortion_tol)
207 const Real R0 = node(0) * n_elems_per_side;
208 CPPUNIT_ASSERT_LESS(distortion_tol*distortion_tol, std::abs(R0-std::round(R0)));
215 libmesh_error_msg(
"Node has unsupported number of boundary ids = " << boundary_ids.size());
220 auto is_internal_subdomain_boundary_node_the_same = [&subdomain_boundary_node_id_to_point]
221 (
const Node & node) {
222 auto it = subdomain_boundary_node_id_to_point.find(node.id());
223 if (it != subdomain_boundary_node_id_to_point.end())
224 return (
Point(node) == subdomain_boundary_node_id_to_point[node.id()]);
231 for (
auto node :
mesh.node_ptr_range())
233 CPPUNIT_ASSERT(center_distortion_is(*node, 0,
true));
234 CPPUNIT_ASSERT(center_distortion_is(*node, 1,
true));
241 if (type ==
TRI3 && is_variational_smoother_type)
243 SquareToParallelogram stp;
250 const unsigned int num_iterations = is_variational_smoother_type ? 1 : 8;
251 for (
unsigned int i=0; i != num_iterations; ++i)
257 if (type ==
TRI3 && is_variational_smoother_type)
259 ParallelogramToSquare pts;
264 for (
auto node :
mesh.node_ptr_range())
266 if (multiple_subdomains)
268 CPPUNIT_ASSERT(is_internal_subdomain_boundary_node_the_same(*node));
272 CPPUNIT_ASSERT(center_distortion_is(*node, 0,
false, 1e-3));
273 CPPUNIT_ASSERT(center_distortion_is(*node, 1,
false, 1e-3));
297 #ifdef LIBMESH_ENABLE_VSMOOTHER 312 testSmoother(
mesh, variational,
TRI3);
320 testSmoother(
mesh, variational,
QUAD4,
true);
322 #endif // LIBMESH_ENABLE_VSMOOTHER ElemType
Defines an enum for geometric element types.
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.
libMesh::Parallel::Communicator * TestCommWorld
static constexpr Real TOLERANCE
void resize(const unsigned int n)
Resize the vector.
void testVariationalQuad()
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 testVariationalTri()
This class defines the data structures necessary for Laplace smoothing.
CPPUNIT_TEST_SUITE_REGISTRATION(MeshSmootherTest)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This is an implementation of Larisa Branets' smoothing algorithms.
void testVariationalQuadMultipleSubdomains()
void testSmoother(ReplicatedMesh &mesh, MeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false)
This class provides the necessary interface for mesh smoothing.
Defines a dense vector for use in Finite Element-type computations.
Base class for functors that can be evaluated at a point and (optionally) time.
A Point defines a location in LIBMESH_DIM dimensional Real space.