Skip to content

Commit db82696

Browse files
committed
Add test for ShellMatrix.
1 parent f2ddeeb commit db82696

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

tests/numerics/shell_matrix.C

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include "libmesh/shell_matrix.h"
2+
#include "libmesh/enum_solver_type.h"
3+
#include "libmesh/sparse_shell_matrix.h"
4+
#ifdef LIBMESH_HAVE_PETSC
5+
#include "libmesh/petsc_linear_solver.h"
6+
#include "libmesh/petsc_vector.h"
7+
#include "libmesh/petsc_matrix.h"
8+
#include "libmesh/petsc_shell_matrix.h"
9+
10+
#include "libmesh_cppunit.h"
11+
#include "test_comm.h"
12+
13+
using namespace libMesh;
14+
15+
class ShellMatrixTest : public CppUnit::TestCase
16+
{
17+
public:
18+
LIBMESH_CPPUNIT_TEST_SUITE(ShellMatrixTest);
19+
20+
CPPUNIT_TEST(testPetscShell);
21+
CPPUNIT_TEST(testSparseShell_petsc);
22+
23+
CPPUNIT_TEST_SUITE_END();
24+
25+
public:
26+
void setUp()
27+
{
28+
_comm = TestCommWorld;
29+
}
30+
31+
void tearDown() {}
32+
33+
void testPetscShell()
34+
{
35+
LOG_UNIT_TEST;
36+
37+
// Depending on the config: Use different vector-types here!
38+
PetscLinearSolver<Number> linear_solver(*_comm);
39+
linear_solver.init();
40+
auto ierr = KSPSetType (linear_solver.ksp(), const_cast<KSPType>(KSPGMRES));
41+
CHKERRABORT(linear_solver.comm().get(), ierr);
42+
ierr = PCSetType (linear_solver.pc(), const_cast<PCType>(PCNONE));
43+
CHKERRABORT(linear_solver.comm().get(), ierr);
44+
KSPSetInitialGuessNonzero(linear_solver.ksp(), PETSC_TRUE);
45+
46+
unsigned int maxits=20;
47+
Real tol = 1e-3;
48+
49+
UnityShellMat mat = (*_comm);
50+
51+
// Depending on the config: Use different vector-types here!
52+
PetscVector<Number> rhs(*_comm, 20);
53+
rhs.set(5,2.);
54+
rhs.close();
55+
auto solution = rhs.clone();
56+
solution->set(7,2.);
57+
solution->close();
58+
linear_solver.solve(mat, *solution, rhs, tol, maxits);
59+
60+
for (numeric_index_type m=0; m < rhs.size(); ++m)
61+
CPPUNIT_ASSERT_EQUAL(solution->el(m), rhs.el(m));
62+
}
63+
64+
void testSparseShell_petsc()
65+
{
66+
LOG_UNIT_TEST;
67+
68+
// Depending on the config: Use different vector-types here!
69+
PetscLinearSolver<Number> linear_solver(*_comm);
70+
linear_solver.init();
71+
auto ierr = KSPSetType (linear_solver.ksp(), const_cast<KSPType>(KSPGMRES));
72+
CHKERRABORT(linear_solver.comm().get(), ierr);
73+
ierr = PCSetType (linear_solver.pc(), const_cast<PCType>(PCNONE));
74+
CHKERRABORT(linear_solver.comm().get(), ierr);
75+
KSPSetInitialGuessNonzero(linear_solver.ksp(), PETSC_TRUE);
76+
77+
PetscMatrix<Number> petsc_mat(*_comm);
78+
petsc_mat.init(20,20,20,20,1,0,1); // hard-coded dimension.
79+
set_unity(petsc_mat);
80+
petsc_mat.close();
81+
SparseShellMatrix<Number> mat(petsc_mat);
82+
83+
unsigned int maxits=20;
84+
Real tol = 1e-3;
85+
86+
// Depending on the config: Use different vector-types here!
87+
PetscVector<Number> rhs(*_comm, 20);
88+
rhs.set(5,2.);
89+
rhs.close();
90+
auto solution = rhs.clone();
91+
solution->set(7,2.);
92+
solution->close();
93+
linear_solver.solve(mat, *solution, rhs, tol, maxits);
94+
95+
for (numeric_index_type m=0; m < rhs.size(); ++m)
96+
CPPUNIT_ASSERT_EQUAL(solution->el(m), rhs.el(m));
97+
98+
// Make the matrix singular:
99+
// a) set an irrelevant element to '0':
100+
solution->set(7,2.);
101+
petsc_mat.set(2,2,0.);
102+
auto rval = linear_solver.solve(mat, *solution, rhs, tol, maxits);
103+
// In this case, we can solve the equation.
104+
CPPUNIT_ASSERT_EQUAL(rval.second, 0.00);
105+
// b) set the relevant element to '0':
106+
petsc_mat.set(5,5,0.);
107+
rval = linear_solver.solve(mat, *solution, rhs, tol, maxits);
108+
// In this case, we can not solve the equation.
109+
// The best solution is the 0-vector and we have an error of 2.0
110+
CPPUNIT_ASSERT_EQUAL(rval.second, 2.00);
111+
112+
}
113+
114+
private:
115+
Parallel::Communicator * _comm;
116+
117+
void set_unity(SparseMatrix<Number> & M)
118+
{
119+
for (libMesh::numeric_index_type n=0; n < M.m(); ++n)
120+
M.set(n,n,1.);
121+
}
122+
123+
class UnityShellMat : public libMesh::ShellMatrix<libMesh::Number>
124+
{
125+
public:
126+
UnityShellMat(Parallel::Communicator & comm):
127+
ShellMatrix(comm){}
128+
129+
virtual ~UnityShellMat() = default;
130+
131+
virtual libMesh::numeric_index_type m () const override
132+
{
133+
return 20;
134+
}
135+
virtual libMesh::numeric_index_type n () const override
136+
{
137+
return 20;
138+
}
139+
140+
virtual void vector_mult(libMesh::NumericVector<libMesh::Number> &dest,
141+
const libMesh::NumericVector< libMesh::Number > &arg) const override
142+
{
143+
dest = arg;
144+
}
145+
146+
virtual void vector_mult_add (libMesh::NumericVector<libMesh::Number> &dest,
147+
const libMesh::NumericVector< libMesh::Number > &arg) const override
148+
{
149+
dest += arg;
150+
}
151+
152+
virtual void get_diagonal (libMesh::NumericVector<libMesh::Number> &dest) const override
153+
{
154+
for (numeric_index_type m=0; m < dest.local_size(); ++m)
155+
dest.set(m, 1.);
156+
}
157+
158+
};
159+
160+
};
161+
162+
CPPUNIT_TEST_SUITE_REGISTRATION(ShellMatrixTest);
163+
164+
#endif // #ifdef LIBMESH_HAVE_PETSC

0 commit comments

Comments
 (0)