libMesh
partitioner_test.h
Go to the documentation of this file.
1 #ifndef __fe_test_h__
2 #define __fe_test_h__
3 
4 #include "test_comm.h"
5 
6 #include <libmesh/distributed_mesh.h>
7 #include <libmesh/elem.h>
8 #include <libmesh/partitioner.h>
9 #include <libmesh/replicated_mesh.h>
10 #include <libmesh/mesh_generation.h>
11 
12 // Ignore unused parameter warnings coming from cppunit headers
13 #include <libmesh/ignore_warnings.h>
14 #include <cppunit/extensions/HelperMacros.h>
15 #include <cppunit/TestCase.h>
16 #include <libmesh/restore_warnings.h>
17 
18 #if LIBMESH_DIM > 2
19 #define PARTITIONERTEST \
20  CPPUNIT_TEST( testPartitionEmpty ); \
21  CPPUNIT_TEST( testPartition1 ); \
22  CPPUNIT_TEST( testPartition2 ); \
23  CPPUNIT_TEST( testPartitionNProc );
24 #else
25 #define PARTITIONERTEST
26 #endif
27 
28 using namespace libMesh;
29 
30 template <typename PartitionerSubclass, typename MeshClass>
31 class PartitionerTest : public CppUnit::TestCase {
32 public:
33  void setUp()
34  {}
35 
36  void tearDown()
37  {}
38 
40  {
41  MeshClass mesh(*TestCommWorld);
42 
44  3, 3, 3,
45  0., 1., 0., 1., 0., 1.,
46  HEX8);
47 
48  // FIXME: Splitting meshes into more than n_proc parts currently
49  // requires us to start with a mesh entirely assigned to proc 0
50  PartitionerSubclass newpart;
51  newpart.partition(mesh, 1);
52 
53  for (auto elem : mesh.element_ptr_range())
54  CPPUNIT_ASSERT_EQUAL(elem->processor_id(), processor_id_type(0));
55 
56  for (auto node : mesh.node_ptr_range())
57  CPPUNIT_ASSERT_EQUAL(node->processor_id(), processor_id_type(0));
58 
59  // But then we can manually partition, into at most many parts as
60  // were requested.
61  newpart.partition(mesh, n_parts);
62 
63  // We expect the partitioner not to suck - every processor
64  // rank (up to n_elem()) ought to have at least one element on it.
65  const processor_id_type n_nonempty =
66  std::min(n_parts, processor_id_type(3*3*3));
67 
68  // Let's make sure we can see them all even on a DistributedMesh
69  mesh.allgather();
70 
71  processor_id_type nonempty_procs = 0;
72  for (processor_id_type p=0; p != n_nonempty; ++p)
73  {
74  const std::size_t n_elem_on_p =
75  std::distance(mesh.pid_elements_begin(p),
76  mesh.pid_elements_end(p));
77  if (n_elem_on_p)
78  nonempty_procs++;
79  }
80 
81  // Unfortunately, it turns out that our METIS and ParMETIS
82  // partitioners *do* suck, and can't reliabily give us more than
83  // 13 non-empty ranks on the above 27 element mesh.
84  CPPUNIT_ASSERT(nonempty_procs >= n_nonempty ||
85  nonempty_procs >= 13);
86  }
87 
89  {
90  MeshClass mesh(*TestCommWorld);
91  PartitionerSubclass newpart;
92 
93  // With a 0 element mesh this should just give us 0 subpartitions
94  // regardless of n_procs
95  newpart.partition(mesh, TestCommWorld->size());
96  }
97 
99  {
100  this->testPartition(1);
101  }
102 
104  {
105  this->testPartition(2);
106  }
107 
109  {
110  this->testPartition(TestCommWorld->size());
111  }
112 };
113 
114 // THE CPPUNIT_TEST_SUITE_END macro expands to code that involves
115 // std::auto_ptr, which in turn produces -Wdeprecated-declarations
116 // warnings. These can be ignored in GCC as long as we wrap the
117 // offending code in appropriate pragmas. We'll put an
118 // ignore_warnings at the end of this file so it's the last warnings
119 // related header that our including code sees.
120 #include <libmesh/ignore_warnings.h>
121 
122 #define INSTANTIATE_PARTITIONER_TEST(partitionersubclass, meshclass) \
123  class PartitionerTest_##partitionersubclass##_##meshclass : \
124  public PartitionerTest<partitionersubclass, meshclass> { \
125  public: \
126  CPPUNIT_TEST_SUITE( PartitionerTest_##partitionersubclass##_##meshclass); \
127  PARTITIONERTEST \
128  CPPUNIT_TEST_SUITE_END(); \
129  }; \
130  \
131  CPPUNIT_TEST_SUITE_REGISTRATION( PartitionerTest_##partitionersubclass##_##meshclass );
132 
133 #endif // #ifdef __fe_test_h__
processor_id_type size() const
Definition: communicator.h:184
libMesh::Parallel::Communicator * TestCommWorld
The libMesh namespace provides an interface to certain functionality in the library.
uint8_t processor_id_type
Definition: id_types.h:104
long double min(long double a, double b)
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.
void testPartition(processor_id_type n_parts)