libMesh
partitioner_test.h
Go to the documentation of this file.
1 #ifndef __fe_test_h__
2 #define __fe_test_h__
3 
4 #include <libmesh/distributed_mesh.h>
5 #include <libmesh/elem.h>
6 #include <libmesh/partitioner.h>
7 #include <libmesh/replicated_mesh.h>
8 #include <libmesh/mesh_generation.h>
9 
10 #include "test_comm.h"
11 #include "libmesh_cppunit.h"
12 
13 
14 #if LIBMESH_DIM > 2
15 #define PARTITIONERTEST \
16  CPPUNIT_TEST( testPartitionEmpty ); \
17  CPPUNIT_TEST( testPartition1 ); \
18  CPPUNIT_TEST( testPartition2 ); \
19  CPPUNIT_TEST( testPartitionNProc );
20 #else
21 #define PARTITIONERTEST
22 #endif
23 
24 using namespace libMesh;
25 
26 template <typename PartitionerSubclass, typename MeshClass>
27 class PartitionerTest : public CppUnit::TestCase {
28 public:
29  void setUp()
30  {}
31 
32  void tearDown()
33  {}
34 
36  {
37  MeshClass mesh(*TestCommWorld);
38 
40  3, 3, 3,
41  0., 1., 0., 1., 0., 1.,
42  HEX8);
43 
44  // FIXME: Splitting meshes into more than n_proc parts currently
45  // requires us to start with a mesh entirely assigned to proc 0
46  PartitionerSubclass newpart;
47  newpart.partition(mesh, 1);
48 
49  for (auto elem : mesh.element_ptr_range())
50  CPPUNIT_ASSERT_EQUAL(elem->processor_id(), processor_id_type(0));
51 
52  for (auto node : mesh.node_ptr_range())
53  CPPUNIT_ASSERT_EQUAL(node->processor_id(), processor_id_type(0));
54 
55  // But then we can manually partition, into at most many parts as
56  // were requested.
57  newpart.partition(mesh, n_parts);
58 
59  // We expect the partitioner not to suck - every processor
60  // rank (up to n_elem()) ought to have at least one element on it.
61  const processor_id_type n_nonempty =
62  std::min(n_parts, processor_id_type(3*3*3));
63 
64  // Let's make sure we can see them all even on a DistributedMesh
65  mesh.allgather();
66 
67  processor_id_type nonempty_procs = 0;
68  for (processor_id_type p=0; p != n_nonempty; ++p)
69  {
70  const std::size_t n_elem_on_p =
73  if (n_elem_on_p)
74  nonempty_procs++;
75  }
76 
77  // Unfortunately, it turns out that our METIS and ParMETIS
78  // partitioners *do* suck, and can't reliabily give us more than
79  // 13 non-empty ranks on the above 27 element mesh.
80  CPPUNIT_ASSERT(nonempty_procs >= n_nonempty ||
81  nonempty_procs >= 13);
82  }
83 
85  {
86  MeshClass mesh(*TestCommWorld);
87  PartitionerSubclass newpart;
88 
89  // With a 0 element mesh this should just give us 0 subpartitions
90  // regardless of n_procs
91  newpart.partition(mesh, TestCommWorld->size());
92  }
93 
95  {
96  this->testPartition(1);
97  }
98 
100  {
101  this->testPartition(2);
102  }
103 
105  {
106  this->testPartition(TestCommWorld->size());
107  }
108 };
109 
110 #define INSTANTIATE_PARTITIONER_TEST(partitionersubclass, meshclass) \
111  class PartitionerTest_##partitionersubclass##_##meshclass : \
112  public PartitionerTest<partitionersubclass, meshclass> { \
113  public: \
114  CPPUNIT_TEST_SUITE( PartitionerTest_##partitionersubclass##_##meshclass); \
115  PARTITIONERTEST \
116  CPPUNIT_TEST_SUITE_END(); \
117  }; \
118  \
119  CPPUNIT_TEST_SUITE_REGISTRATION( PartitionerTest_##partitionersubclass##_##meshclass );
120 
121 #endif // #ifdef __fe_test_h__
libMesh::MeshBase::pid_elements_begin
virtual element_iterator pid_elements_begin(processor_id_type proc_id)=0
Iterate over all elements with a specified processor id.
PartitionerTest
Definition: partitioner_test.h:27
libMesh::HEX8
Definition: enum_elem_type.h:47
libMesh::MeshBase::pid_elements_end
virtual element_iterator pid_elements_end(processor_id_type proc_id)=0
PartitionerTest::testPartition2
void testPartition2()
Definition: partitioner_test.h:99
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
PartitionerTest::testPartition
void testPartition(processor_id_type n_parts)
Definition: partitioner_test.h:35
libMesh::MeshTools::Generation::build_cube
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.
Definition: mesh_generation.C:298
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::element_ptr_range
virtual SimpleRange< element_iterator > element_ptr_range()=0
libMesh::MeshBase::node_ptr_range
virtual SimpleRange< node_iterator > node_ptr_range()=0
TestCommWorld
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:111
libMesh::processor_id_type
uint8_t processor_id_type
Definition: id_types.h:104
PartitionerTest::testPartitionNProc
void testPartitionNProc()
Definition: partitioner_test.h:104
PartitionerTest::testPartition1
void testPartition1()
Definition: partitioner_test.h:94
libMesh::MeshBase::allgather
virtual void allgather()
Gathers all elements and nodes of the mesh onto every processor.
Definition: mesh_base.h:188
distance
Real distance(const Point &p)
Definition: subdomains_ex3.C:50
libmesh_cppunit.h
PartitionerTest::setUp
void setUp()
Definition: partitioner_test.h:29
test_comm.h
PartitionerTest::tearDown
void tearDown()
Definition: partitioner_test.h:32
PartitionerTest::testPartitionEmpty
void testPartitionEmpty()
Definition: partitioner_test.h:84