libMesh
diagonal_matrix_test.C
Go to the documentation of this file.
1 // libmesh includes
2 #include <libmesh/diagonal_matrix.h>
3 #include <libmesh/parallel.h>
4 #include <libmesh/auto_ptr.h>
5 #include <libmesh/dense_matrix.h>
6 #include <libmesh/id_types.h>
7 #include <libmesh/numeric_vector.h>
8 
9 #include "libmesh_cppunit.h"
10 #include "test_comm.h"
11 
12 #include <memory>
13 #include <numeric>
14 
15 #define UNUSED 0
16 
17 using namespace libMesh;
18 
19 namespace
20 {
21 template <typename T>
22 T
23 termial(T n)
24 {
25  return n * (n + 1) / 2;
26 }
27 }
28 
29 class DiagonalMatrixTest : public CppUnit::TestCase
30 {
31 public:
32  CPPUNIT_TEST_SUITE(DiagonalMatrixTest);
33 
34  CPPUNIT_TEST(testSizes);
35  CPPUNIT_TEST(testNumerics);
36 
37  CPPUNIT_TEST_SUITE_END();
38 
39 public:
40  void setUp()
41  {
42  _comm = TestCommWorld;
43  _matrix = libmesh_make_unique<DiagonalMatrix<Number>>(*_comm);
44 
45  numeric_index_type root_block_size = 2;
46  _local_size = root_block_size + static_cast<numeric_index_type>(_comm->rank());
47  _global_size = 0;
48  _i.push_back(0);
49 
50  for (processor_id_type p = 0; p < _comm->size(); ++p)
51  {
52  numeric_index_type block_size = root_block_size + static_cast<numeric_index_type>(p);
53  _global_size += block_size;
54  _i.push_back(_global_size);
55  }
56 
57  _matrix->init(_global_size, UNUSED, _local_size, UNUSED);
58  }
59 
60  void tearDown() {}
61 
62  void testSizes()
63  {
64  CPPUNIT_ASSERT_EQUAL(_global_size, _matrix->m());
65  CPPUNIT_ASSERT_EQUAL(_global_size, _matrix->n());
66  CPPUNIT_ASSERT_EQUAL(_i[_comm->rank()], _matrix->row_start());
67  CPPUNIT_ASSERT_EQUAL(_i[_comm->rank() + 1], _matrix->row_stop());
68  }
69 
70  void testNumerics()
71  {
72  numeric_index_type beginning_index = _matrix->row_start();
73  numeric_index_type end_index = _matrix->row_stop();
74 
75  CPPUNIT_ASSERT_EQUAL(_local_size, numeric_index_type(_matrix->row_stop() - _matrix->row_start()));
76 
77  _matrix->zero();
78 
79  // In general we don't want to mix these calls without an intervening close(), but since these
80  // calls are not actually doing anything for this matrix type it's ok here
81  _matrix->add(beginning_index, beginning_index + 1, 1);
82  _matrix->set(beginning_index + 1, beginning_index, 1);
83 
84  // Test that off-diagonal elements are always zero
85  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(beginning_index, beginning_index + 1)), 0, _tolerance);
86  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(beginning_index + 1, beginning_index)), 0, _tolerance);
87 
88  // Test add
89  {
90  for (numeric_index_type i = beginning_index; i < end_index; ++i)
91  _matrix->add(i, i, i);
92 
93  // Also add to rank 0
94  _matrix->add(0, 0, 1);
95 
96  CPPUNIT_ASSERT(!_matrix->closed());
97 
98  _matrix->close();
99  CPPUNIT_ASSERT(_matrix->closed());
100 
101  for (numeric_index_type i = beginning_index; i < end_index; ++i)
102  {
103  if (i)
104  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), i, _tolerance);
105  else
106  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), _comm->size(), _tolerance);
107  }
108  }
109 
110  // Test set
111  {
112  for (numeric_index_type i = beginning_index; i < end_index; ++i)
113  if (i != _global_size - 1)
114  _matrix->set(i, i, i);
115 
116  if (_comm->rank() == 0)
117  _matrix->set(_global_size - 1, _global_size - 1, 0);
118 
119  CPPUNIT_ASSERT(!_matrix->closed());
120 
121  _matrix->close();
122  CPPUNIT_ASSERT(_matrix->closed());
123 
124  for (numeric_index_type i = beginning_index; i < end_index; ++i)
125  {
126  if (i != _global_size - 1)
127  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), i, _tolerance);
128  else
129  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), 0, _tolerance);
130  }
131  }
132 
133  std::vector<numeric_index_type> rows(_local_size);
134  std::iota(rows.begin(), rows.end(), beginning_index);
135 
136  // Test dense matrix add, get diagonal, SparseMatrix add, get transpose
137  {
138  DenseMatrix<Number> dense(_local_size, _local_size);
139 
140  for (numeric_index_type local_index = 0, global_index = beginning_index;
141  local_index < _local_size;
142  ++local_index, ++global_index)
143  dense(local_index, local_index) = global_index;
144 
145  _matrix->zero();
146 
147  // rows-columns overload for DenseMatrix add
148  _matrix->add_matrix(dense, rows, rows);
149 
150  // Close not really necessary here because we didn't do anything off-process but still good
151  // practice
152  _matrix->close();
153 
154  for (numeric_index_type i = beginning_index; i < end_index; ++i)
155  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), i, _tolerance);
156 
157  // Build
158  auto diagonal = NumericVector<Number>::build(*_comm);
159  // Allocate storage
160  diagonal->init(_matrix->diagonal());
161  // Fill entries
162  _matrix->get_diagonal(*diagonal);
163 
164  // Build
165  DiagonalMatrix<Number> copy(*_comm);
166  // Allocate storage
167  copy.init(*_matrix);
168  // Fill entries from diagonal
169  copy = std::move(*diagonal);
170 
171  // Single dof-indices overload for DenseMatrix add
172  _matrix->add_matrix(dense, rows);
173  _matrix->close();
174 
175  for (numeric_index_type i = beginning_index; i < end_index; ++i)
176  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), 2 * i, _tolerance);
177 
178  // SparseMatrix add
179  _matrix->add(-1, copy);
180 
181  for (numeric_index_type i = beginning_index; i < end_index; ++i)
182  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, i)), i, _tolerance);
183 
184  _matrix->get_transpose(copy);
185 
186  for (numeric_index_type i = beginning_index; i < end_index; ++i)
187  LIBMESH_ASSERT_FP_EQUAL(libmesh_real(copy(i, i)), i, _tolerance);
188  }
189 
190  // Test norms
191  {
192  LIBMESH_ASSERT_FP_EQUAL(termial(_global_size - 1), _matrix->l1_norm(), _tolerance);
193  LIBMESH_ASSERT_FP_EQUAL(_global_size - 1, _matrix->linfty_norm(), _tolerance);
194  }
195 
196  // Test zero_rows
197  {
198  _matrix->zero_rows(rows, 1);
199  for (numeric_index_type i = beginning_index; i < end_index; ++i)
200  for (numeric_index_type j = beginning_index; j < end_index; ++j)
201  {
202  if (i == j)
203  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, j)), 1, _tolerance);
204  else
205  LIBMESH_ASSERT_FP_EQUAL(libmesh_real((*_matrix)(i, j)), 0, _tolerance);
206  }
207  }
208  }
209 
210 private:
211 
212  Parallel::Communicator * _comm;
213  std::unique_ptr<DiagonalMatrix<Number>> _matrix;
215  std::vector<numeric_index_type> _i;
216  const Real _tolerance = TOLERANCE * TOLERANCE;
217 };
218 
libMesh::DiagonalMatrix::init
void init(const numeric_index_type m, const numeric_index_type n, const numeric_index_type m_l, const numeric_index_type n_l, const numeric_index_type nnz=30, const numeric_index_type noz=10, const numeric_index_type blocksize=1) override
Initialize SparseMatrix with the specified sizes.
Definition: diagonal_matrix.C:54
libMesh::libmesh_real
T libmesh_real(T a)
Definition: libmesh_common.h:166
DiagonalMatrixTest::_comm
Parallel::Communicator * _comm
Definition: diagonal_matrix_test.C:212
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
DiagonalMatrixTest::_i
std::vector< numeric_index_type > _i
Definition: diagonal_matrix_test.C:215
DiagonalMatrixTest::_local_size
numeric_index_type _local_size
Definition: diagonal_matrix_test.C:214
libMesh::TOLERANCE
static const Real TOLERANCE
Definition: libmesh_common.h:128
libMesh::DenseMatrix< Number >
DiagonalMatrixTest::testNumerics
void testNumerics()
Definition: diagonal_matrix_test.C:70
DiagonalMatrixTest::_matrix
std::unique_ptr< DiagonalMatrix< Number > > _matrix
Definition: diagonal_matrix_test.C:213
DiagonalMatrixTest::tearDown
void tearDown()
Definition: diagonal_matrix_test.C:60
DiagonalMatrixTest
Definition: diagonal_matrix_test.C:29
libMesh::DiagonalMatrix
Diagonal matrix class whose underlying storage is a vector.
Definition: diagonal_matrix.h:42
libMesh::NumericVector::build
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
Definition: numeric_vector.C:49
libMesh::Utility::iota
void iota(ForwardIter first, ForwardIter last, T value)
Utility::iota is a duplication of the SGI STL extension std::iota.
Definition: utility.h:105
DiagonalMatrixTest::testSizes
void testSizes()
Definition: diagonal_matrix_test.C:62
TestCommWorld
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:111
libMesh::processor_id_type
uint8_t processor_id_type
Definition: id_types.h:104
libMesh::DenseMatrix::zero
virtual void zero() override
Set every element in the matrix to 0.
Definition: dense_matrix.h:838
libMesh::numeric_index_type
dof_id_type numeric_index_type
Definition: id_types.h:99
libmesh_cppunit.h
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
test_comm.h
DiagonalMatrixTest::setUp
void setUp()
Definition: diagonal_matrix_test.C:40
CPPUNIT_TEST_SUITE_REGISTRATION
CPPUNIT_TEST_SUITE_REGISTRATION(DiagonalMatrixTest)