Skip to content

Commit 40c7bbc

Browse files
committed
Merge pull request #64 from danielru/feature/scalar_tests
Very nice! High fives!
2 parents 024b40f + 09e90e2 commit 40c7bbc

File tree

5 files changed

+140
-15
lines changed

5 files changed

+140
-15
lines changed

examples/scalar/scalar_sdc.cpp

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/*
2+
* Scalar test equation example using an encapsulated IMEX sweeper.
3+
* Solves Dahlquist's test equation
4+
* y' = a y + i b y
5+
* treating the real part implicitly and the imaginary part explicitly.
6+
*/
7+
18
#include<complex>
29

310
#include<pfasst.hpp>
@@ -6,32 +13,45 @@
613

714
#include "scalar_sweeper.hpp"
815

9-
int main(int, char**)
16+
/*
17+
* A simple run routine with preset parameters
18+
*/
19+
20+
double run_scalar_sdc(const size_t nsteps, const double dt, const size_t nnodes,
21+
const size_t niters, const complex<double> lambda)
1022
{
23+
1124
pfasst::SDC<> sdc;
1225

13-
const size_t nsteps = 2;
14-
const double dt = 1.0;
15-
const size_t nnodes = 4;
16-
const size_t niters = 6;
17-
const complex<double> lambda = complex<double>(-1.0, 1.0);
1826
const complex<double> y0 = complex<double>(1.0, 0.0);
19-
20-
// so far, only lobatto nodes appear to be working
21-
auto nodes = pfasst::compute_nodes(nnodes, "gauss-lobatto");
27+
auto nodes = pfasst::compute_nodes(nnodes, "gauss-lobatto");
2228
auto factory = make_shared<pfasst::encap::VectorFactory<complex<double>>>(1);
23-
auto sweeper = make_shared<ScalarSweeper<>>(lambda, y0);
24-
29+
auto sweeper = make_shared<ScalarSweeper<>>(lambda,y0);
30+
2531
sweeper->set_nodes(nodes);
2632
sweeper->set_factory(factory);
27-
33+
2834
sdc.add_level(sweeper);
29-
sdc.set_duration(0.0, dt * nsteps, dt, niters);
35+
sdc.set_duration(0.0, dt*nsteps, dt, niters);
3036
sdc.setup();
31-
37+
3238
auto q0 = sweeper->get_state(0);
3339
sweeper->exact(q0, 0.0);
34-
40+
3541
sdc.run();
42+
43+
return sweeper->get_errors();
44+
}
3645

46+
#ifndef PFASST_UNIT_TESTING
47+
int main(int /*argc*/, char** /*argv*/)
48+
{
49+
const size_t nsteps = 2;
50+
const double dt = 1.0;
51+
const size_t nnodes = 4;
52+
const size_t niters = 6;
53+
const complex<double> lambda = complex<double>(-1.0, 1.0);
54+
55+
run_scalar_sdc(nsteps, dt, nnodes, niters, lambda);
3756
}
57+
#endif

examples/scalar/scalar_sweeper.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ScalarSweeper : public pfasst::encap::IMEXSweeper<time>
3232

3333
virtual ~ScalarSweeper()
3434
{
35+
cout << "Final error: " << scientific << this->_error << endl;
3536
cout << "Number of calls to f1eval: " << this->_nf1eval << endl;
3637
cout << "Number of calls to f2eval: " << this->_nf2eval << endl;
3738
cout << "Number of calls to f2comp: " << this->_nf2comp << endl;
@@ -46,6 +47,12 @@ class ScalarSweeper : public pfasst::encap::IMEXSweeper<time>
4647
this->exact(qex, t);
4748
double max_err = abs(qend[0] - qex[0]) / abs(qex[0]);
4849
cout << "err: " << scientific << max_err << endl;
50+
this->_error = max_err;
51+
}
52+
53+
double get_errors()
54+
{
55+
return this->_error;
4956
}
5057

5158
void predict(bool initial) override
@@ -121,6 +128,7 @@ class ScalarSweeper : public pfasst::encap::IMEXSweeper<time>
121128
complex<double> _lambda, _y0;
122129
int _nf1eval, _nf2eval, _nf2comp;
123130
const complex<double> i_complex = complex<double>(0, 1);
131+
double _error;
124132

125133
};
126134
#endif

tests/examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11

22
add_subdirectory(advection_diffusion)
3+
add_subdirectory(scalar)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Building and Running Tests
2+
include_directories(
3+
${3rdparty_INCLUDES}
4+
${pfasst_INCLUDES}
5+
)
6+
7+
set(TESTS
8+
test_scalar
9+
)
10+
11+
foreach(test ${TESTS})
12+
message(STATUS " ${test}")
13+
add_executable(${test} ${test}.cpp)
14+
add_dependencies(${test} googlemock)
15+
target_link_libraries(${test}
16+
${3rdparty_DEPENDEND_LIBS}
17+
${pfasst_DEPENDED_LIBS}
18+
)
19+
set_target_properties(${test}
20+
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tests/examples/scalar
21+
)
22+
add_test(NAME ${test}
23+
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tests/examples/scalar/${test} --gtest_output=xml:${test}_out.xml
24+
)
25+
endforeach(test)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Tests for the scalar example solving the test equation
3+
*/
4+
5+
#include <cmath>
6+
#include <gtest/gtest.h>
7+
#include <gmock/gmock.h>
8+
9+
#define PFASST_UNIT_TESTING
10+
#include "../examples/scalar/scalar_sdc.cpp"
11+
#undef PFASST_UNIT_TESTING
12+
13+
MATCHER (DoubleMore, "")
14+
{
15+
return get<0>(arg) > get<1>(arg);
16+
}
17+
18+
19+
/*
20+
* For Lobatto nodes, the resulting method should of order 2*M-2 with M=number of nodes
21+
* The test below verifies that the code approximately (up to a safety factor) reproduces
22+
* the theoretically expected rate of convergence
23+
*/
24+
TEST(ConvergenceTest, ScalarSDC)
25+
{
26+
27+
const complex<double> lambda = complex<double>(-1.0, 1.0);
28+
const double Tend = 4.0;
29+
const vector<size_t> nsteps = { 2, 5, 10, 15, 20 };
30+
size_t nsteps_l = nsteps.size();
31+
32+
vector<double> err(nsteps.size());
33+
vector<double> convrate(nsteps.size()-1);
34+
35+
double dt;
36+
37+
// Test converge up to 6 nodes: For more nodes, errors are of the order of machine
38+
// precision and convergence can no longer be monitored
39+
for ( size_t nnodes = 2; nnodes<=6; ++nnodes)
40+
{
41+
// Expect convergence rate of 2*nodes-2 from collocation formula,
42+
// doing an identical number of iteration should suffice to reach this as each
43+
// iteration should increase order by one
44+
size_t niters = 2*nnodes-2;
45+
46+
for ( size_t i = 0; i<=nsteps_l-1; ++i)
47+
{
48+
dt = Tend/double(nsteps[i]);
49+
err[i] = run_scalar_sdc(nsteps[i], dt, nnodes, niters, lambda);
50+
}
51+
52+
for ( size_t i = 0; i<=nsteps_l-2; ++i)
53+
{
54+
convrate[i] = log10(err[i+1]/err[i])/log10(double(nsteps[i])/double(nsteps[i+1]));
55+
56+
EXPECT_THAT(convrate[i], testing::DoubleNear(double(2*nnodes-2), 0.99)) << "Convergence rate at node " << i << " not within expected range";
57+
}
58+
59+
// NOTE: There is probably a much more elegant way to test this, because
60+
// expected_cr contains the same value in all entries. But I could not so far figure
61+
// out how to build a more clever MATCHER here so far....
62+
// EXPECT_THAT(convrate, testing::Pointwise(DoubleMore(), expected_cr ));
63+
64+
}
65+
}
66+
67+
int main(int argc, char** argv)
68+
{
69+
testing::InitGoogleTest(&argc, argv);
70+
return RUN_ALL_TESTS();
71+
}

0 commit comments

Comments
 (0)