libMesh
Public Member Functions | List of all members
MeshSmootherTest Class Reference
Inheritance diagram for MeshSmootherTest:
[legend]

Public Member Functions

 LIBMESH_CPPUNIT_TEST_SUITE (MeshSmootherTest)
 The goal of this test is to verify proper operation of the MeshSmoother subclasses. More...
 
 CPPUNIT_TEST (testLaplaceQuad)
 
 CPPUNIT_TEST (testLaplaceTri)
 
 CPPUNIT_TEST (testVariationalEdge2)
 
 CPPUNIT_TEST (testVariationalEdge3)
 
 CPPUNIT_TEST (testVariationalEdge3MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalQuad4)
 
 CPPUNIT_TEST (testVariationalQuad4MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalQuad8)
 
 CPPUNIT_TEST (testVariationalQuad9)
 
 CPPUNIT_TEST (testVariationalQuad9MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalQuad4Tangled)
 
 CPPUNIT_TEST (testVariationalTri3)
 
 CPPUNIT_TEST (testVariationalTri6)
 
 CPPUNIT_TEST (testVariationalTri6MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalHex8)
 
 CPPUNIT_TEST (testVariationalHex20)
 
 CPPUNIT_TEST (testVariationalHex27)
 
 CPPUNIT_TEST (testVariationalHex27Tangled)
 
 CPPUNIT_TEST (testVariationalHex27MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalPyramid5)
 
 CPPUNIT_TEST (testVariationalPyramid13)
 
 CPPUNIT_TEST (testVariationalPyramid14)
 
 CPPUNIT_TEST (testVariationalPyramid18)
 
 CPPUNIT_TEST (testVariationalPyramid18MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalPrism6)
 
 CPPUNIT_TEST (testVariationalPrism15)
 
 CPPUNIT_TEST (testVariationalPrism18)
 
 CPPUNIT_TEST (testVariationalPrism20)
 
 CPPUNIT_TEST (testVariationalPrism21)
 
 CPPUNIT_TEST (testVariationalPrism21MultipleSubdomains)
 
 CPPUNIT_TEST (testVariationalMixed2D)
 
 CPPUNIT_TEST (testVariationalMixed3D)
 
 CPPUNIT_TEST_SUITE_END ()
 
void setUp ()
 
void tearDown ()
 
void testLaplaceSmoother (ReplicatedMesh &mesh, MeshSmoother &smoother, ElemType type)
 
void testVariationalSmoother (ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
 
void testVariationalSmootherRegression (const ReplicatedMesh &gold_mesh)
 
void testLaplaceQuad ()
 
void testLaplaceTri ()
 
void testVariationalEdge2 ()
 
void testVariationalEdge3 ()
 
void testVariationalEdge3MultipleSubdomains ()
 
void testVariationalQuad4 ()
 
void testVariationalQuad4MultipleSubdomains ()
 
void testVariationalQuad8 ()
 
void testVariationalQuad9 ()
 
void testVariationalQuad9MultipleSubdomains ()
 
void testVariationalQuad4Tangled ()
 
void testVariationalTri3 ()
 
void testVariationalTri6 ()
 
void testVariationalTri6MultipleSubdomains ()
 
void testVariationalHex8 ()
 
void testVariationalHex20 ()
 
void testVariationalHex27 ()
 
void testVariationalHex27MultipleSubdomains ()
 
void testVariationalHex27Tangled ()
 
void testVariationalPyramid5 ()
 
void testVariationalPyramid13 ()
 
void testVariationalPyramid14 ()
 
void testVariationalPyramid18 ()
 
void testVariationalPyramid18MultipleSubdomains ()
 
void testVariationalPrism6 ()
 
void testVariationalPrism15 ()
 
void testVariationalPrism18 ()
 
void testVariationalPrism20 ()
 
void testVariationalPrism21 ()
 
void testVariationalPrism21MultipleSubdomains ()
 
void testVariationalMixed2D ()
 
void testVariationalMixed3D ()
 

Detailed Description

Definition at line 220 of file mesh_smoother_test.C.

Member Function Documentation

◆ CPPUNIT_TEST() [1/32]

MeshSmootherTest::CPPUNIT_TEST ( testLaplaceQuad  )

◆ CPPUNIT_TEST() [2/32]

MeshSmootherTest::CPPUNIT_TEST ( testLaplaceTri  )

◆ CPPUNIT_TEST() [3/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalEdge2  )

◆ CPPUNIT_TEST() [4/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalEdge3  )

◆ CPPUNIT_TEST() [5/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalEdge3MultipleSubdomains  )

◆ CPPUNIT_TEST() [6/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalQuad4  )

◆ CPPUNIT_TEST() [7/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalQuad4MultipleSubdomains  )

◆ CPPUNIT_TEST() [8/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalQuad8  )

◆ CPPUNIT_TEST() [9/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalQuad9  )

◆ CPPUNIT_TEST() [10/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalQuad9MultipleSubdomains  )

◆ CPPUNIT_TEST() [11/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalQuad4Tangled  )

◆ CPPUNIT_TEST() [12/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalTri3  )

◆ CPPUNIT_TEST() [13/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalTri6  )

◆ CPPUNIT_TEST() [14/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalTri6MultipleSubdomains  )

◆ CPPUNIT_TEST() [15/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalHex8  )

◆ CPPUNIT_TEST() [16/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalHex20  )

◆ CPPUNIT_TEST() [17/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalHex27  )

◆ CPPUNIT_TEST() [18/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalHex27Tangled  )

◆ CPPUNIT_TEST() [19/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalHex27MultipleSubdomains  )

◆ CPPUNIT_TEST() [20/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPyramid5  )

◆ CPPUNIT_TEST() [21/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPyramid13  )

◆ CPPUNIT_TEST() [22/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPyramid14  )

◆ CPPUNIT_TEST() [23/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPyramid18  )

◆ CPPUNIT_TEST() [24/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPyramid18MultipleSubdomains  )

◆ CPPUNIT_TEST() [25/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPrism6  )

◆ CPPUNIT_TEST() [26/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPrism15  )

◆ CPPUNIT_TEST() [27/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPrism18  )

◆ CPPUNIT_TEST() [28/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPrism20  )

◆ CPPUNIT_TEST() [29/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPrism21  )

◆ CPPUNIT_TEST() [30/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalPrism21MultipleSubdomains  )

◆ CPPUNIT_TEST() [31/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalMixed2D  )

◆ CPPUNIT_TEST() [32/32]

MeshSmootherTest::CPPUNIT_TEST ( testVariationalMixed3D  )

◆ CPPUNIT_TEST_SUITE_END()

MeshSmootherTest::CPPUNIT_TEST_SUITE_END ( )

◆ LIBMESH_CPPUNIT_TEST_SUITE()

MeshSmootherTest::LIBMESH_CPPUNIT_TEST_SUITE ( MeshSmootherTest  )

The goal of this test is to verify proper operation of the MeshSmoother subclasses.

◆ setUp()

void MeshSmootherTest::setUp ( )
inline

Definition at line 278 of file mesh_smoother_test.C.

278 {}

◆ tearDown()

void MeshSmootherTest::tearDown ( )
inline

Definition at line 280 of file mesh_smoother_test.C.

280 {}

◆ testLaplaceQuad()

void MeshSmootherTest::testLaplaceQuad ( )
inline

Definition at line 745 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD4, and TestCommWorld.

746  {
748  LaplaceMeshSmoother laplace(mesh);
749 
750  testLaplaceSmoother(mesh, laplace, QUAD4);
751  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
void testLaplaceSmoother(ReplicatedMesh &mesh, MeshSmoother &smoother, ElemType type)
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
This class defines the data structures necessary for Laplace smoothing.

◆ testLaplaceSmoother()

void MeshSmootherTest::testLaplaceSmoother ( ReplicatedMesh mesh,
MeshSmoother smoother,
ElemType  type 
)
inline

Definition at line 282 of file mesh_smoother_test.C.

References libMesh::MeshTools::Generation::build_square(), mesh, libMesh::Real, libMesh::MeshTools::Modification::redistribute(), libMesh::MeshSmoother::smooth(), and libMesh::TOLERANCE.

283  {
284  LOG_UNIT_TEST;
285 
286  constexpr unsigned int n_elems_per_side = 4;
287 
289  mesh, n_elems_per_side, n_elems_per_side, 0., 1., 0., 1., type);
290 
291  // Move it around so we have something that needs smoothing
292  DistortSquare ds;
294 
295  // Assert the distortion is as expected
296  auto center_distortion_is =
297  [](const Node & node, int d, bool distortion, Real distortion_tol = TOLERANCE) {
298  const Real r = node(d);
299  const Real R = r * n_elems_per_side;
300  CPPUNIT_ASSERT_GREATER(-TOLERANCE * TOLERANCE, r);
301  CPPUNIT_ASSERT_GREATER(-TOLERANCE * TOLERANCE, 1 - r);
302 
303  // If we're at the boundaries we should *never* be distorted
304  if (std::abs(node(0)) < TOLERANCE * TOLERANCE ||
305  std::abs(node(0) - 1) < TOLERANCE * TOLERANCE)
306  {
307  const Real R1 = node(1) * n_elems_per_side;
308  CPPUNIT_ASSERT_LESS(TOLERANCE * TOLERANCE, std::abs(R1 - std::round(R1)));
309  return true;
310  }
311 
312  if (std::abs(node(1)) < TOLERANCE * TOLERANCE ||
313  std::abs(node(1) - 1) < TOLERANCE * TOLERANCE)
314  {
315  const Real R0 = node(0) * n_elems_per_side;
316  CPPUNIT_ASSERT_LESS(TOLERANCE * TOLERANCE, std::abs(R0 - std::round(R0)));
317 
318  return true;
319  }
320 
321  // If we're at the center we're fine
322  if (std::abs(r - 0.5) < TOLERANCE * TOLERANCE)
323  return true;
324 
325  return ((std::abs(R - std::round(R)) > distortion_tol) == distortion);
326  };
327 
328  for (auto node : mesh.node_ptr_range())
329  {
330  CPPUNIT_ASSERT(center_distortion_is(*node, 0, true));
331  CPPUNIT_ASSERT(center_distortion_is(*node, 1, true));
332  }
333 
334  // Enough iterations to mostly fix us up. Laplace seems to be at 1e-3
335  // tolerance by iteration 6, so hopefully everything is there on any
336  // system by 8.
337  for (unsigned int i = 0; i != 8; ++i)
338  smoother.smooth();
339 
340  // Make sure we're not too distorted anymore.
341  for (auto node : mesh.node_ptr_range())
342  {
343  CPPUNIT_ASSERT(center_distortion_is(*node, 0, false, 1e-3));
344  CPPUNIT_ASSERT(center_distortion_is(*node, 1, false, 1e-3));
345  }
346  }
A Node is like a Point, but with more information.
Definition: node.h:52
static constexpr Real TOLERANCE
MeshBase & mesh
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
virtual void smooth()=0
Function which actually performs the smoothing operations.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void redistribute(MeshBase &mesh, const FunctionBase< Real > &mapfunc)
Deterministically perturb the nodal locations.

◆ testLaplaceTri()

void MeshSmootherTest::testLaplaceTri ( )
inline

Definition at line 753 of file mesh_smoother_test.C.

References mesh, TestCommWorld, and libMesh::TRI3.

754  {
756  LaplaceMeshSmoother laplace(mesh);
757 
758  testLaplaceSmoother(mesh, laplace, TRI3);
759  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
void testLaplaceSmoother(ReplicatedMesh &mesh, MeshSmoother &smoother, ElemType type)
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
This class defines the data structures necessary for Laplace smoothing.

◆ testVariationalEdge2()

void MeshSmootherTest::testVariationalEdge2 ( )
inline

Definition at line 762 of file mesh_smoother_test.C.

References libMesh::EDGE2, mesh, and TestCommWorld.

763  {
765  VariationalMeshSmoother variational(mesh);
766 
767  testVariationalSmoother(mesh, variational, EDGE2);
768  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalEdge3()

void MeshSmootherTest::testVariationalEdge3 ( )
inline

Definition at line 770 of file mesh_smoother_test.C.

References libMesh::EDGE3, mesh, and TestCommWorld.

771  {
773  VariationalMeshSmoother variational(mesh);
774 
775  testVariationalSmoother(mesh, variational, EDGE3);
776  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalEdge3MultipleSubdomains()

void MeshSmootherTest::testVariationalEdge3MultipleSubdomains ( )
inline

Definition at line 778 of file mesh_smoother_test.C.

References libMesh::EDGE3, mesh, and TestCommWorld.

779  {
781  VariationalMeshSmoother variational(mesh);
782 
783  testVariationalSmoother(mesh, variational, EDGE3, true);
784  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalHex20()

void MeshSmootherTest::testVariationalHex20 ( )
inline

Definition at line 866 of file mesh_smoother_test.C.

References libMesh::HEX20, mesh, and TestCommWorld.

867  {
869  VariationalMeshSmoother variational(mesh);
870 
871  testVariationalSmoother(mesh, variational, HEX20);
872  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalHex27()

void MeshSmootherTest::testVariationalHex27 ( )
inline

Definition at line 874 of file mesh_smoother_test.C.

References libMesh::HEX27, mesh, and TestCommWorld.

875  {
877  VariationalMeshSmoother variational(mesh);
878 
879  testVariationalSmoother(mesh, variational, HEX27);
880  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalHex27MultipleSubdomains()

void MeshSmootherTest::testVariationalHex27MultipleSubdomains ( )
inline

Definition at line 882 of file mesh_smoother_test.C.

References libMesh::HEX27, mesh, and TestCommWorld.

883  {
885  VariationalMeshSmoother variational(mesh);
886 
887  testVariationalSmoother(mesh, variational, HEX27, true);
888  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalHex27Tangled()

void MeshSmootherTest::testVariationalHex27Tangled ( )
inline

Definition at line 890 of file mesh_smoother_test.C.

References libMesh::HEX27, mesh, and TestCommWorld.

891  {
893  VariationalMeshSmoother variational(mesh);
894 
895  testVariationalSmoother(mesh, variational, HEX27, false, true, 0.55);
896  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalHex8()

void MeshSmootherTest::testVariationalHex8 ( )
inline

Definition at line 858 of file mesh_smoother_test.C.

References libMesh::HEX8, mesh, and TestCommWorld.

859  {
861  VariationalMeshSmoother variational(mesh);
862 
863  testVariationalSmoother(mesh, variational, HEX8);
864  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalMixed2D()

void MeshSmootherTest::testVariationalMixed2D ( )
inline

Definition at line 990 of file mesh_smoother_test.C.

References mesh, libMesh::MeshBase::read(), and TestCommWorld.

991  {
993  mesh.read("meshes/quad4_tri3_smoothed.xda.gz");
994 
996  }
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.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmootherRegression(const ReplicatedMesh &gold_mesh)

◆ testVariationalMixed3D()

void MeshSmootherTest::testVariationalMixed3D ( )
inline

Definition at line 998 of file mesh_smoother_test.C.

References mesh, libMesh::MeshBase::read(), and TestCommWorld.

999  {
1001  mesh.read("meshes/hex8_prism6_smoothed.xda.gz");
1002 
1004  }
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.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmootherRegression(const ReplicatedMesh &gold_mesh)

◆ testVariationalPrism15()

void MeshSmootherTest::testVariationalPrism15 ( )
inline

Definition at line 946 of file mesh_smoother_test.C.

References mesh, libMesh::PRISM15, and TestCommWorld.

947  {
949  VariationalMeshSmoother variational(mesh);
950 
951  testVariationalSmoother(mesh, variational, PRISM15);
952  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPrism18()

void MeshSmootherTest::testVariationalPrism18 ( )
inline

Definition at line 954 of file mesh_smoother_test.C.

References mesh, libMesh::PRISM18, TestCommWorld, and libMesh::TOLERANCE.

955  {
957  VariationalMeshSmoother variational(
958  mesh, 0.5, true, TOLERANCE * TOLERANCE, 10 * TOLERANCE * TOLERANCE);
959 
960  testVariationalSmoother(mesh, variational, PRISM18);
961  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
static constexpr Real TOLERANCE
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPrism20()

void MeshSmootherTest::testVariationalPrism20 ( )
inline

Definition at line 963 of file mesh_smoother_test.C.

References mesh, libMesh::PRISM20, TestCommWorld, and libMesh::TOLERANCE.

964  {
966  VariationalMeshSmoother variational(
967  mesh, 0.5, true, TOLERANCE * TOLERANCE, 10 * TOLERANCE * TOLERANCE);
968 
969  testVariationalSmoother(mesh, variational, PRISM20);
970  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
static constexpr Real TOLERANCE
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPrism21()

void MeshSmootherTest::testVariationalPrism21 ( )
inline

Definition at line 972 of file mesh_smoother_test.C.

References mesh, libMesh::PRISM21, TestCommWorld, and libMesh::TOLERANCE.

973  {
975  VariationalMeshSmoother variational(
976  mesh, 0.5, true, TOLERANCE * TOLERANCE, 10 * TOLERANCE * TOLERANCE);
977 
978  testVariationalSmoother(mesh, variational, PRISM21);
979  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
static constexpr Real TOLERANCE
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPrism21MultipleSubdomains()

void MeshSmootherTest::testVariationalPrism21MultipleSubdomains ( )
inline

Definition at line 981 of file mesh_smoother_test.C.

References libMesh::MeshBase::allow_renumbering(), mesh, libMesh::PRISM21, and TestCommWorld.

982  {
984  mesh.allow_renumbering(false);
985  VariationalMeshSmoother variational(mesh);
986 
987  testVariationalSmoother(mesh, variational, PRISM21, true);
988  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
Definition: mesh_base.h:1196
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPrism6()

void MeshSmootherTest::testVariationalPrism6 ( )
inline

Definition at line 938 of file mesh_smoother_test.C.

References mesh, libMesh::PRISM6, and TestCommWorld.

939  {
941  VariationalMeshSmoother variational(mesh);
942 
943  testVariationalSmoother(mesh, variational, PRISM6);
944  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPyramid13()

void MeshSmootherTest::testVariationalPyramid13 ( )
inline

Definition at line 906 of file mesh_smoother_test.C.

References mesh, libMesh::PYRAMID13, and TestCommWorld.

907  {
909  VariationalMeshSmoother variational(mesh);
910 
911  testVariationalSmoother(mesh, variational, PYRAMID13);
912  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPyramid14()

void MeshSmootherTest::testVariationalPyramid14 ( )
inline

Definition at line 914 of file mesh_smoother_test.C.

References mesh, libMesh::PYRAMID14, and TestCommWorld.

915  {
917  VariationalMeshSmoother variational(mesh);
918 
919  testVariationalSmoother(mesh, variational, PYRAMID14);
920  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPyramid18()

void MeshSmootherTest::testVariationalPyramid18 ( )
inline

Definition at line 922 of file mesh_smoother_test.C.

References mesh, libMesh::PYRAMID18, and TestCommWorld.

923  {
925  VariationalMeshSmoother variational(mesh);
926 
927  testVariationalSmoother(mesh, variational, PYRAMID18);
928  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPyramid18MultipleSubdomains()

void MeshSmootherTest::testVariationalPyramid18MultipleSubdomains ( )
inline

Definition at line 930 of file mesh_smoother_test.C.

References mesh, libMesh::PYRAMID18, and TestCommWorld.

931  {
933  VariationalMeshSmoother variational(mesh);
934 
935  testVariationalSmoother(mesh, variational, PYRAMID18, true);
936  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalPyramid5()

void MeshSmootherTest::testVariationalPyramid5 ( )
inline

Definition at line 898 of file mesh_smoother_test.C.

References mesh, libMesh::PYRAMID5, and TestCommWorld.

899  {
901  VariationalMeshSmoother variational(mesh);
902 
903  testVariationalSmoother(mesh, variational, PYRAMID5);
904  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalQuad4()

void MeshSmootherTest::testVariationalQuad4 ( )
inline

Definition at line 786 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD4, and TestCommWorld.

787  {
789  VariationalMeshSmoother variational(mesh);
790 
791  testVariationalSmoother(mesh, variational, QUAD4);
792  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalQuad4MultipleSubdomains()

void MeshSmootherTest::testVariationalQuad4MultipleSubdomains ( )
inline

Definition at line 794 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD4, and TestCommWorld.

795  {
797  VariationalMeshSmoother variational(mesh);
798 
799  testVariationalSmoother(mesh, variational, QUAD4, true);
800  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalQuad4Tangled()

void MeshSmootherTest::testVariationalQuad4Tangled ( )
inline

Definition at line 826 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD4, and TestCommWorld.

827  {
829  VariationalMeshSmoother variational(mesh);
830 
831  testVariationalSmoother(mesh, variational, QUAD4, false, true, 0.65);
832  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalQuad8()

void MeshSmootherTest::testVariationalQuad8 ( )
inline

Definition at line 802 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD8, and TestCommWorld.

803  {
805  VariationalMeshSmoother variational(mesh);
806 
807  testVariationalSmoother(mesh, variational, QUAD8);
808  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalQuad9()

void MeshSmootherTest::testVariationalQuad9 ( )
inline

Definition at line 810 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD9, and TestCommWorld.

811  {
813  VariationalMeshSmoother variational(mesh);
814 
815  testVariationalSmoother(mesh, variational, QUAD9);
816  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalQuad9MultipleSubdomains()

void MeshSmootherTest::testVariationalQuad9MultipleSubdomains ( )
inline

Definition at line 818 of file mesh_smoother_test.C.

References mesh, libMesh::QUAD9, and TestCommWorld.

819  {
821  VariationalMeshSmoother variational(mesh);
822 
823  testVariationalSmoother(mesh, variational, QUAD9, true);
824  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalSmoother()

void MeshSmootherTest::testVariationalSmoother ( ReplicatedMesh mesh,
VariationalMeshSmoother smoother,
const ElemType  type,
const bool  multiple_subdomains = false,
const bool  tangle_mesh = false,
const Real  tangle_damping_factor = 1.0 
)
inline

Definition at line 348 of file mesh_smoother_test.C.

References libMesh::absolute_fuzzy_equals(), TIMPI::Communicator::broadcast(), libMesh::MeshTools::Generation::build_cube(), libMesh::MeshTools::Generation::build_line(), libMesh::MeshTools::Generation::build_square(), libMesh::ParallelObject::comm(), dim, libMesh::MeshBase::elem_default_orders(), libMesh::Utility::enum_to_string(), libMesh::ReferenceElem::get(), libMesh::MeshBase::get_boundary_info(), libMesh::VariationalMeshSmoother::get_mesh_info(), libMesh::DofObject::invalid_id, libMesh::libmesh_assert(), libMesh::make_range(), mesh, TIMPI::Communicator::minloc(), libMesh::MeshBase::node_ref(), libMesh::TensorTools::norm(), libMesh::PYRAMID18, libMesh::Real, libMesh::MeshTools::Modification::redistribute(), libMesh::relative_fuzzy_equals(), libMesh::VariationalMeshSmoother::setup(), libMesh::VariationalMeshSmoother::smooth(), libMesh::Parallel::sync_dofobject_data_by_id(), libMesh::TOLERANCE, and libMesh::Elem::type_to_default_order_map.

354  {
355  LOG_UNIT_TEST;
356 
357  if (multiple_subdomains && tangle_mesh)
358  libmesh_not_implemented_msg(
359  "Arbitrary mesh tangling with multiple subdomains is not supported.");
360 
361  // Get mesh dimension, determine whether type is triangular
362  const auto * ref_elem = &(ReferenceElem::get(type));
363  const auto dim = ref_elem->dim();
364  const bool type_is_tri = Utility::enum_to_string(type).compare(0, 3, "TRI") == 0;
365  const bool type_is_pyramid = Utility::enum_to_string(type).compare(0, 7, "PYRAMID") == 0;
366  const bool type_is_prism = Utility::enum_to_string(type).compare(0, 5, "PRISM") == 0;
367 
368  // Used fewer elems for higher order types, as extra midpoint nodes will add
369  // enough complexity
370  unsigned int n_elems_per_side = 4 / Elem::type_to_default_order_map[type];
371 
372  switch (dim)
373  {
374  case 1:
375  MeshTools::Generation::build_line(mesh, n_elems_per_side, 0., 1., type);
376  break;
377  case 2:
379  mesh, n_elems_per_side, n_elems_per_side, 0., 1., 0., 1., type);
380  break;
381 
382  case 3:
384  n_elems_per_side,
385  n_elems_per_side,
386  n_elems_per_side,
387  0.,
388  1.,
389  0.,
390  1.,
391  0.,
392  1.,
393  type);
394  break;
395 
396  default:
397  libmesh_error_msg("Unsupported dimension " << dim);
398  }
399 
400  // Move it around so we have something that needs smoothing
401  DistortHyperCube dh(dim);
403 
404  const auto & boundary_info = mesh.get_boundary_info();
405 
406  if (tangle_mesh)
407  {
408  // We tangle the mesh by (partially) swapping the locations of 2 nodes.
409  // If the n-dimentional hypercube is represented as a grid with
410  // (undistorted) divisions occuring at integer numbers, we will
411  // (partially) swap the nodes nearest p1 = (1,1,1) and p2 = (2,1,2).
412 
413  // Define p1 and p2 given the integer indices
414  // Undistorted elem side length
415  const Real dr = 1. / (n_elems_per_side * Elem::type_to_default_order_map[type]);
416  const Point p1 = Point(dr, dim > 1 ? dr : 0, dim > 2 ? dr : 0);
417  const Point p2 = Point(2. * dr, dim > 1 ? dr : 0, dim > 2 ? 2. * dr : 0);
418 
419  // ids and distances of mesh nodes nearest p1 and p2
420  dof_id_type node1_id = DofObject::invalid_id;
421  Real dist1_closest = std::numeric_limits<Real>::max();
422  dof_id_type node2_id = DofObject::invalid_id;
423  Real dist2_closest = std::numeric_limits<Real>::max();
424 
425  for (const auto * node : mesh.local_node_ptr_range())
426  {
427  const auto dist1 = (*node - p1).norm();
428  if (dist1 < dist1_closest)
429  {
430  dist1_closest = dist1;
431  node1_id = node->id();
432  }
433 
434  const auto dist2 = (*node - p2).norm();
435  if (dist2 < dist2_closest)
436  {
437  dist2_closest = dist2;
438  node2_id = node->id();
439  }
440  }
441 
442  // parallel communication
443  unsigned int node1_rank;
444  mesh.comm().minloc(dist1_closest, node1_rank);
445  mesh.comm().broadcast(node1_id, node1_rank);
446 
447  unsigned int node2_rank;
448  mesh.comm().minloc(dist2_closest, node2_rank);
449  mesh.comm().broadcast(node2_id, node2_rank);
450 
451  // modify the nodes
452  if ((node1_id != DofObject::invalid_id) && (node2_id != DofObject::invalid_id))
453  {
454  libmesh_assert(node1_id != node2_id);
455 
456  auto & node1 = mesh.node_ref(node1_id);
457  auto & node2 = mesh.node_ref(node2_id);
458 
459  const Point diff = node1 - node2;
460  // Note that a damping factor of 1 will swap the nodes and one
461  // of 0.5 will move the nodes to the mean of their original
462  // locations.
463  node1 -= tangle_damping_factor * diff;
464  node2 += tangle_damping_factor * diff;
465  }
466 
467  SyncNodalPositions sync_object(mesh);
468  Parallel::sync_dofobject_data_by_id (mesh.comm(), mesh.nodes_begin(), mesh.nodes_end(), sync_object);
469 
470  // Make sure the mesh is tangled
471  smoother.setup(); // Need this to create the system we are about to access
472  const auto & unsmoothed_info = smoother.get_mesh_info();
473  CPPUNIT_ASSERT(unsmoothed_info.mesh_is_tangled);
474  }
475 
476  // Add multiple subdomains if requested
477  std::unordered_map<subdomain_id_type, Real> distorted_subdomain_volumes;
478  if (multiple_subdomains)
479  {
480  // Modify the subdomain ids in an interesting way
481  for (auto * elem : mesh.active_element_ptr_range())
482  {
483  unsigned int subdomain_id = 0;
484  for (const auto d : make_range(dim))
485  if (elem->vertex_average()(d) > 0.5)
486  ++subdomain_id;
487  elem->subdomain_id() += subdomain_id;
488  }
489 
490  // This loop should NOT be combined with the one above because we need to
491  // finish checking and updating subdomain ids for all elements before
492  // recording the final subdomain volumes.
493  for (auto * elem : mesh.active_element_ptr_range())
494  distorted_subdomain_volumes[elem->subdomain_id()] += elem->volume();
495  }
496 
497  // Get the mesh order
498  const auto & elem_orders = mesh.elem_default_orders();
499  libmesh_error_msg_if(elem_orders.size() != 1,
500  "The variational smoother cannot be used for mixed-order meshes!");
501  // For pyramids, the factor 2 accounts for the account that cubes of side
502  // length s are divided into pyramids of base side length s and height s/2.
503  // The factor 4 lets us catch triangular face midpoint nodes for PYRAMID18 elements.
504  const auto scale_factor = *elem_orders.begin() * (type_is_pyramid ? 2 * 4 : 1);
505 
506  // Function to assert the node distortion is as expected
507  auto node_distortion_is = [&n_elems_per_side, &dim, &boundary_info, &scale_factor, &type_is_prism](
508  const Node & node, bool distortion, Real distortion_tol = TOLERANCE) {
509  // Get boundary ids associated with the node
510  std::vector<boundary_id_type> boundary_ids;
511  boundary_info.boundary_ids(&node, boundary_ids);
512 
513  // This tells us what type of node we are: internal, sliding, or fixed
514  const auto num_dofs = dim - boundary_ids.size();
515  /*
516  * The following cases of num_dofs are possible, ASSUMING all boundaries
517  * are non-overlapping
518  * 3D: 3-0, 3-1, 3-2, 3-3
519  * = 3 2 1 0
520  * internal sliding, sliding, fixed
521  * 2D: 2-0, 2-1, 2-2
522  * = 2 1 0
523  * internal sliding, fixed
524  * 1D: 1-0, 1-1
525  * = 1 0
526  * internal fixed
527  *
528  * We expect that R is an integer in [0, n_elems_per_side] for
529  * num_dofs of the node's cooridinantes, while the remaining coordinates
530  * are fixed to the boundary with value 0 or 1. In other words, at LEAST
531  * dim - num_dofs coordinantes should be 0 or 1.
532  */
533 
534  std::size_t num_zero_or_one = 0;
535 
536  bool distorted = false;
537  for (const auto d : make_range(dim))
538  {
539  const Real r = node(d);
540  const Real R = r * n_elems_per_side * scale_factor;
541  CPPUNIT_ASSERT_GREATER(-distortion_tol * distortion_tol, r);
542  CPPUNIT_ASSERT_GREATER(-distortion_tol * distortion_tol, 1 - r);
543 
544  bool d_distorted = std::abs(R - std::round(R)) > distortion_tol;
545  if (type_is_prism && (scale_factor == 3))
546  {
547  // Adjustment required for triangular face nodes of PRISM20/21 elements.
548  // These elements have fe_order 3. This takes care of nodes occuring at
549  // thirds, but not halves.
550  const Real R_prism = R / scale_factor * 2;
551  const bool d_distorted_prism =
552  std::abs(R_prism - std::round(R_prism)) > distortion_tol;
553  d_distorted &= d_distorted_prism;
554  }
555  distorted |= d_distorted;
556  num_zero_or_one += (absolute_fuzzy_equals(r, 0.) || absolute_fuzzy_equals(r, 1.));
557  }
558 
559  CPPUNIT_ASSERT_GREATEREQUAL(dim - num_dofs, num_zero_or_one);
560 
561  // We can never expect a fixed node to be distorted
562  if (num_dofs == 0)
563  // if (num_dofs < dim)
564  return true;
565  return distorted == distortion;
566  };
567 
568  // Make sure our DistortHyperCube transformation has distorted the mesh
569  for (auto node : mesh.node_ptr_range())
570  CPPUNIT_ASSERT(node_distortion_is(*node, true));
571 
572  // Transform the square mesh of triangles to a parallelogram mesh of
573  // triangles. This will allow the Variational Smoother to smooth the mesh
574  // to the optimal case of equilateral triangles
575  if (type_is_tri)
576  {
577  // Transform the square mesh of triangles to a parallelogram mesh of
578  // triangles. This will allow the Variational Smoother to smooth the mesh
579  // to the optimal case of equilateral triangles
580  SquareToParallelogram stp;
582  }
583  else if (type_is_prism)
584  {
585  // Transform the cube mesh of prisms to a parallelepiped mesh of
586  // prisms. This will allow the Variational Smoother to smooth the mesh
587  // to the optimal case of equilateral triangular prisms
588  CubeToParallelepiped ctp;
590  }
591 
592  smoother.smooth();
593 
594  if (type_is_tri)
595  {
596  // Transform the parallelogram mesh back to a square mesh. In the case of
597  // the Variational Smoother, equilateral triangules will be transformed
598  // into right triangules that align with the original undistorted mesh.
599  ParallelogramToSquare pts;
601  }
602  else if (type_is_prism)
603  {
604  // Transform the parallelepiped mesh back to a cube mesh. In the case of
605  // the Variational Smoother, equilateral triangular prisms will be transformed
606  // into right triangular prisms that align with the original undistorted mesh.
607  ParallelepipedToCube ptc;
609  }
610 
611  if (multiple_subdomains)
612  {
613  // Make sure the subdomain volumes didn't change. Although this doesn't
614  // guarantee that the subdomain didn't change, it is a good indicator
615  // and is friedly to sliding subdomain boundary nodes.
616  std::unordered_map<subdomain_id_type, Real> smoothed_subdomain_volumes;
617  for (auto * elem : mesh.active_element_ptr_range())
618  smoothed_subdomain_volumes[elem->subdomain_id()] += elem->volume();
619 
620  for (const auto & pair : distorted_subdomain_volumes)
621  {
622  const auto & subdomain_id = pair.first;
623  CPPUNIT_ASSERT(
624  relative_fuzzy_equals(libmesh_map_find(distorted_subdomain_volumes, subdomain_id),
625  libmesh_map_find(smoothed_subdomain_volumes, subdomain_id),
626  TOLERANCE));
627  }
628  }
629  else
630  {
631  // Make sure we're not too distorted anymore
632  std::set<dof_id_type> nodes_checked;
633  for (const auto * elem : mesh.active_element_ptr_range())
634  {
635  for (const auto local_node_id : make_range(elem->n_nodes()))
636  {
637  const auto & node = elem->node_ref(local_node_id);
638  if (nodes_checked.find(node.id()) != nodes_checked.end())
639  continue;
640 
641  nodes_checked.insert(node.id());
642 
643  // Check for special case where pyramidal base-to-apex midpoint
644  // nodes are not smoothed to the actual midpoints.
645  if (type_is_pyramid)
646  {
647  if (local_node_id > 8 && local_node_id < 13)
648  {
649  // Base-Apex midpoint nodes
650  //
651  // Due to the nature of the pyramidal target element and the
652  // cubic nature of the test mesh, for a dilation weight o
653  // 0.5, smoothed base-apex midpoint nodes are smoothed to
654  // the point base + x * (apex - base) instead of
655  // base + 0.5 (apex - base), where x is in (0,1) and
656  // depends on the number of nodes in the element.
657  // We hard-code this check below.
658 
659  const auto & base = elem->node_ref(local_node_id - 9);
660  const auto & apex = elem->node_ref(4);
661  const Real x = (type == PYRAMID18) ? 0.569332 : 0.549876;
662 
663  CPPUNIT_ASSERT(node.relative_fuzzy_equals(base + x * (apex - base), 1e-3));
664  continue;
665  }
666  else if (local_node_id > 13)
667  {
668  // Triangular face midpoint nodes
669  //
670  // Due to the nature of the pyramidal target element and the
671  // cubic nature of the test mesh, for a dilation weight o
672  // 0.5, smoothed triangular face midpoint nodes are
673  // smoothed a weighted average of the constituent
674  // vertices instead of an unweighted average.
675  // We hard-code this check below.
676  const auto & base1 = elem->node_ref(local_node_id - 14);
677  const auto & base2 = elem->node_ref((local_node_id - 13) % 4);
678  const auto & apex = elem->node_ref(4);
679 
680  const auto node_approx = (0.3141064847 * base1 +
681  0.3141064847 * base2 +
682  0.3717870306 * apex);
683  CPPUNIT_ASSERT(node.relative_fuzzy_equals(node_approx, 1e-3));
684  continue;
685  }
686  }
687 
688  CPPUNIT_ASSERT(node_distortion_is(node, false, 1e-2));
689 
690  }
691  }
692  }
693  }
const std::set< Order > & elem_default_orders() const
Definition: mesh_base.h:289
A Node is like a Point, but with more information.
Definition: node.h:52
void minloc(T &r, unsigned int &min_id) const
static constexpr Real TOLERANCE
unsigned int dim
MeshBase & mesh
const MeshQualityInfo & get_mesh_info() const
Getter for the _system&#39;s _mesh_info attribute.
const Parallel::Communicator & comm() const
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:165
libmesh_assert(ctx)
auto norm(const T &a) -> decltype(std::abs(a))
Definition: tensor_tools.h:74
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.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
std::string enum_to_string(const T e)
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.
Definition: fuzzy_equals.h:64
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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...
Definition: int_range.h:140
void redistribute(MeshBase &mesh, const FunctionBase< Real > &mapfunc)
Deterministically perturb the nodal locations.
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:596
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.
Definition: fuzzy_equals.h:78
virtual void setup()
Setup method that creates equation systems, system, and constraints, to be called just prior to smoot...
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
const Elem & get(const ElemType type_in)
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
virtual void smooth() override
Redefinition of the smooth function from the base class.
uint8_t dof_id_type
Definition: id_types.h:67

◆ testVariationalSmootherRegression()

void MeshSmootherTest::testVariationalSmootherRegression ( const ReplicatedMesh gold_mesh)
inline

Definition at line 697 of file mesh_smoother_test.C.

References libMesh::make_range(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::ReplicatedMesh::n_nodes(), libMesh::MeshBase::n_nodes(), libMesh::MeshBase::node_ref(), libMesh::Real, libMesh::MeshTools::Modification::redistribute(), libMesh::VariationalMeshSmoother::smooth(), and libMesh::TOLERANCE.

698  {
699  // Make a copy of the gold mesh to distort and then smooth
700  ReplicatedMesh mesh(gold_mesh);
701 
702  // Move it around so we have something that needs smoothing
703  DistortHyperCube dh(mesh.mesh_dimension());
705 
706  // Function to assert the distortion is as expected
707  auto mesh_distortion_is = [](const ReplicatedMesh & gold_mesh,
708  const ReplicatedMesh & mesh,
709  const bool distortion,
710  Real distortion_tol = TOLERANCE) {
711 
712  CPPUNIT_ASSERT(gold_mesh.n_nodes() == mesh.n_nodes());
713  for (const auto node_id : make_range(gold_mesh.n_nodes()))
714  {
715  const auto & gold_node = gold_mesh.node_ref(node_id);
716  const auto & node = mesh.node_ref(node_id);
717  for (const auto d : make_range(gold_mesh.mesh_dimension()))
718  {
719  const bool d_distorted = std::abs(gold_node(d) - node(d)) > distortion_tol;
720  if (d_distorted)
721  // mesh is distorted from gold_mesh
722  return distortion;
723  }
724  }
725 
726  // mesh is not distorted from gold_mesh
727  return !distortion;
728  };
729 
730  // Make sure the mesh has been distorted
731  CPPUNIT_ASSERT(mesh_distortion_is(gold_mesh, mesh, true));
732 
733  // Turn off subdomain boundary preservation because DistortHyperCube
734  // does not preserve subdomain boundaries
735  // Also set dilation coefficient to 0 because the reference volume of the
736  // distorted mesh won't be equal to the reference volume of the smoothed
737  // mesh and will smooth to a slightly different solution.
738  VariationalMeshSmoother smoother(mesh, 0.0, false);
739  smoother.smooth();
740 
741  // Make sure the mesh has been smoothed to the gold mesh
742  CPPUNIT_ASSERT(mesh_distortion_is(gold_mesh, mesh, false));
743  }
virtual dof_id_type n_nodes() const override final
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
static constexpr Real TOLERANCE
MeshBase & mesh
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This is an implementation of Larisa Branets&#39; smoothing algorithms.
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...
Definition: int_range.h:140
unsigned int mesh_dimension() const
Definition: mesh_base.C:372
void redistribute(MeshBase &mesh, const FunctionBase< Real > &mapfunc)
Deterministically perturb the nodal locations.
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:596
virtual dof_id_type n_nodes() const =0

◆ testVariationalTri3()

void MeshSmootherTest::testVariationalTri3 ( )
inline

Definition at line 834 of file mesh_smoother_test.C.

References mesh, TestCommWorld, and libMesh::TRI3.

835  {
837  VariationalMeshSmoother variational(mesh);
838 
839  testVariationalSmoother(mesh, variational, TRI3);
840  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalTri6()

void MeshSmootherTest::testVariationalTri6 ( )
inline

Definition at line 842 of file mesh_smoother_test.C.

References mesh, TestCommWorld, and libMesh::TRI6.

843  {
845  VariationalMeshSmoother variational(mesh);
846 
847  testVariationalSmoother(mesh, variational, TRI6);
848  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

◆ testVariationalTri6MultipleSubdomains()

void MeshSmootherTest::testVariationalTri6MultipleSubdomains ( )
inline

Definition at line 850 of file mesh_smoother_test.C.

References mesh, TestCommWorld, and libMesh::TRI3.

851  {
853  VariationalMeshSmoother variational(mesh);
854 
855  testVariationalSmoother(mesh, variational, TRI3, true);
856  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
MeshBase & mesh
void testVariationalSmoother(ReplicatedMesh &mesh, VariationalMeshSmoother &smoother, const ElemType type, const bool multiple_subdomains=false, const bool tangle_mesh=false, const Real tangle_damping_factor=1.0)
This is an implementation of Larisa Branets&#39; smoothing algorithms.

The documentation for this class was generated from the following file: