libMesh
Loading...
Searching...
No Matches
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/dense_matrix.h>
5#include <libmesh/id_types.h>
6#include <libmesh/numeric_vector.h>
7
8#include "libmesh_cppunit.h"
9#include "test_comm.h"
10
11#include <memory>
12#include <numeric>
13
14#define UNUSED 0
15
16using namespace libMesh;
17
18namespace
19{
20template <typename T>
21T
22termial(T n)
23{
24 return n * (n + 1) / 2;
25}
26}
27
28class DiagonalMatrixTest : public CppUnit::TestCase
29{
30public:
32
36
38
39public:
40 void setUp()
41 {
43 _matrix = std::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 LOG_UNIT_TEST;
65
66 CPPUNIT_ASSERT_EQUAL(_global_size, _matrix->m());
67 CPPUNIT_ASSERT_EQUAL(_global_size, _matrix->n());
68 CPPUNIT_ASSERT_EQUAL(_i[_comm->rank()], _matrix->row_start());
69 CPPUNIT_ASSERT_EQUAL(_i[_comm->rank() + 1], _matrix->row_stop());
70 }
71
73 {
74 LOG_UNIT_TEST;
75
76 numeric_index_type beginning_index = _matrix->row_start();
77 numeric_index_type end_index = _matrix->row_stop();
78
79 CPPUNIT_ASSERT_EQUAL(_local_size, numeric_index_type(_matrix->row_stop() - _matrix->row_start()));
80
81 _matrix->zero();
82
83 // In general we don't want to mix these calls without an intervening close(), but since these
84 // calls are not actually doing anything for this matrix type it's ok here
85 _matrix->add(beginning_index, beginning_index + 1, 1);
86 _matrix->set(beginning_index + 1, beginning_index, 1);
87
88 // Test that off-diagonal elements are always zero
89 LIBMESH_ASSERT_NUMBERS_EQUAL(0, (*_matrix)(beginning_index, beginning_index + 1), _tolerance);
90 LIBMESH_ASSERT_NUMBERS_EQUAL(0, (*_matrix)(beginning_index + 1, beginning_index), _tolerance);
91
92 // Test add
93 {
94 for (numeric_index_type i = beginning_index; i < end_index; ++i)
95 _matrix->add(i, i, i);
96
97 // Also add to rank 0
98 _matrix->add(0, 0, 1);
99
100 CPPUNIT_ASSERT(!_matrix->closed());
101
102 _matrix->close();
103 CPPUNIT_ASSERT(_matrix->closed());
104
105 for (numeric_index_type i = beginning_index; i < end_index; ++i)
106 {
107 if (i)
108 LIBMESH_ASSERT_NUMBERS_EQUAL((*_matrix)(i, i), i, _tolerance);
109 else
110 LIBMESH_ASSERT_NUMBERS_EQUAL((*_matrix)(i, i), _comm->size(), _tolerance);
111 }
112 }
113
114 // Test set
115 {
116 for (numeric_index_type i = beginning_index; i < end_index; ++i)
117 if (i != _global_size - 1)
118 _matrix->set(i, i, i);
119
120 if (_comm->rank() == 0)
121 _matrix->set(_global_size - 1, _global_size - 1, 0);
122
123 CPPUNIT_ASSERT(!_matrix->closed());
124
125 _matrix->close();
126 CPPUNIT_ASSERT(_matrix->closed());
127
128 for (numeric_index_type i = beginning_index; i < end_index; ++i)
129 {
130 if (i != _global_size - 1)
131 LIBMESH_ASSERT_NUMBERS_EQUAL(i, (*_matrix)(i, i), _tolerance);
132 else
133 LIBMESH_ASSERT_NUMBERS_EQUAL(0, (*_matrix)(i, i), _tolerance);
134 }
135 }
136
137 std::vector<numeric_index_type> rows(_local_size);
138 std::iota(rows.begin(), rows.end(), beginning_index);
139
140 // Test dense matrix add, get diagonal, SparseMatrix add, get transpose
141 {
143
144 for (numeric_index_type local_index = 0, global_index = beginning_index;
145 local_index < _local_size;
146 ++local_index, ++global_index)
147 dense(local_index, local_index) = global_index;
148
149 _matrix->zero();
150
151 // rows-columns overload for DenseMatrix add
152 _matrix->add_matrix(dense, rows, rows);
153
154 // Close not really necessary here because we didn't do anything off-process but still good
155 // practice
156 _matrix->close();
157
158 for (numeric_index_type i = beginning_index; i < end_index; ++i)
159 LIBMESH_ASSERT_NUMBERS_EQUAL(i, (*_matrix)(i, i), _tolerance);
160
161 // Build
162 auto diagonal = NumericVector<Number>::build(*_comm);
163 // Allocate storage
164 diagonal->init(_matrix->diagonal());
165 // Fill entries
166 _matrix->get_diagonal(*diagonal);
167
168 // Build
170 // Allocate storage
171 copy.init(*_matrix);
172 // Fill entries from diagonal
173 copy = std::move(*diagonal);
174
175 // Single dof-indices overload for DenseMatrix add
176 _matrix->add_matrix(dense, rows);
177 _matrix->close();
178
179 for (numeric_index_type i = beginning_index; i < end_index; ++i)
180 LIBMESH_ASSERT_NUMBERS_EQUAL(2 * i, (*_matrix)(i, i), _tolerance);
181
182 // SparseMatrix add
183 _matrix->add(-1, copy);
184
185 for (numeric_index_type i = beginning_index; i < end_index; ++i)
186 LIBMESH_ASSERT_NUMBERS_EQUAL(i, (*_matrix)(i, i), _tolerance);
187
188 _matrix->get_transpose(copy);
189
190 for (numeric_index_type i = beginning_index; i < end_index; ++i)
191 LIBMESH_ASSERT_NUMBERS_EQUAL(i, copy(i, i), _tolerance);
192 }
193
194 // Test norms
195 {
196 LIBMESH_ASSERT_FP_EQUAL(termial(_global_size - 1), _matrix->l1_norm(), _tolerance);
197 LIBMESH_ASSERT_FP_EQUAL(_global_size - 1, _matrix->linfty_norm(), _tolerance);
198 }
199
200 // Test zero_rows
201 {
202 _matrix->zero_rows(rows, 1);
203 for (numeric_index_type i = beginning_index; i < end_index; ++i)
204 for (numeric_index_type j = beginning_index; j < end_index; ++j)
205 {
206 if (i == j)
207 LIBMESH_ASSERT_NUMBERS_EQUAL(1, (*_matrix)(i, j), _tolerance);
208 else
209 LIBMESH_ASSERT_NUMBERS_EQUAL(0, (*_matrix)(i, j), _tolerance);
210 }
211 }
212 }
213
215 {
216 LOG_UNIT_TEST;
217
218 {
219 // Create copy, test that it can go out of scope
220 auto copy = _matrix->clone();
221
222 // Check that matrices have the same local/global sizes
223 CPPUNIT_ASSERT_EQUAL(copy->m(), _matrix->m());
224 CPPUNIT_ASSERT_EQUAL(copy->n(), _matrix->n());
225 CPPUNIT_ASSERT_EQUAL(copy->local_m(), _matrix->local_m());
226 CPPUNIT_ASSERT_EQUAL(copy->row_start(), _matrix->row_start());
227 CPPUNIT_ASSERT_EQUAL(copy->row_stop(), _matrix->row_stop());
228
229 // Check that copy has same values as original
230 LIBMESH_ASSERT_FP_EQUAL(copy->l1_norm(), _matrix->l1_norm(), _tolerance);
231 }
232
233 {
234 // Create zero copy
235 auto zero_copy = _matrix->zero_clone();
236
237 // Check that matrices have the same local/global sizes
238 CPPUNIT_ASSERT_EQUAL(zero_copy->m(), _matrix->m());
239 CPPUNIT_ASSERT_EQUAL(zero_copy->n(), _matrix->n());
240 CPPUNIT_ASSERT_EQUAL(zero_copy->local_m(), _matrix->local_m());
241 CPPUNIT_ASSERT_EQUAL(zero_copy->row_start(), _matrix->row_start());
242 CPPUNIT_ASSERT_EQUAL(zero_copy->row_stop(), _matrix->row_stop());
243
244 // Check that zero_copy has same values as original
245 LIBMESH_ASSERT_FP_EQUAL(0.0, zero_copy->l1_norm(), _tolerance);
246 }
247 }
248
249private:
250
252 std::unique_ptr<DiagonalMatrix<Number>> _matrix;
254 std::vector<numeric_index_type> _i;
256};
257
CPPUNIT_TEST(testClone)
CPPUNIT_TEST(testSizes)
std::vector< numeric_index_type > _i
numeric_index_type _global_size
Parallel::Communicator * _comm
std::unique_ptr< DiagonalMatrix< Number > > _matrix
LIBMESH_CPPUNIT_TEST_SUITE(DiagonalMatrixTest)
numeric_index_type _local_size
CPPUNIT_TEST(testNumerics)
processor_id_type size() const
processor_id_type rank() const
Defines a dense matrix for use in Finite Element-type computations.
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
Diagonal matrix class whose underlying storage is a vector.
virtual 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.
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
CPPUNIT_TEST_SUITE_REGISTRATION(DiagonalMatrixTest)
Communicator * TestCommWorld
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type numeric_index_type
Definition id_types.h:99
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104