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));
A Node is like a Point, but with more information.
static constexpr Real TOLERANCE
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.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This is an implementation of Larisa Branets' smoothing algorithms.
A Point defines a location in LIBMESH_DIM dimensional Real space.