Skip to content

Commit bf914b5

Browse files
author
Daniel
committed
added a test for the scalar example that verifies convergence orders for up to six lobatto nodes
1 parent 33e3112 commit bf914b5

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

examples/scalar/scalar_sdc.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
#include "scalar_sweeper.hpp"
1515

16+
/*
17+
* A simple run routine with preset parameters
18+
*/
1619
double run_scalar_sdc()
1720
{
1821
pfasst::SDC<> sdc;
@@ -44,6 +47,35 @@ double run_scalar_sdc()
4447
return sweeper->get_errors();
4548
}
4649

50+
/*
51+
* Overloaded run routine, which requires necessary parameters to be passed as arguments
52+
*/
53+
double run_scalar_sdc(const size_t nsteps, const double dt, const size_t nnodes,
54+
const size_t niters, const complex<double> lambda)
55+
{
56+
57+
pfasst::SDC<> sdc;
58+
59+
const complex<double> y0 = complex<double>(1.0, 0.0);
60+
auto nodes = pfasst::compute_nodes(nnodes, "gauss-lobatto");
61+
auto factory = make_shared<pfasst::encap::VectorFactory<complex<double>>>(1);
62+
auto sweeper = make_shared<ScalarSweeper<>>(lambda,y0);
63+
64+
sweeper->set_nodes(nodes);
65+
sweeper->set_factory(factory);
66+
67+
sdc.add_level(sweeper);
68+
sdc.set_duration(0.0, dt*nsteps, dt, niters);
69+
sdc.setup();
70+
71+
auto q0 = sweeper->get_state(0);
72+
sweeper->exact(q0, 0.0);
73+
74+
sdc.run();
75+
76+
return sweeper->get_errors();
77+
}
78+
4779
#ifndef PFASST_UNIT_TESTING
4880
int main(int /*argc*/, char** /*argv*/)
4981
{

examples/scalar/scalar_sweeper.hpp

Lines changed: 1 addition & 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;

tests/examples/scalar/test_scalar.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,70 @@
11
/*
22
* Tests for the scalar example solving the test equation
33
*/
4-
4+
5+
#include <cmath>
56
#include <gtest/gtest.h>
67
#include <gmock/gmock.h>
78

89
#define PFASST_UNIT_TESTING
910
#include "../examples/scalar/scalar_sdc.cpp"
1011
#undef PFASST_UNIT_TESTING
1112

13+
MATCHER (DoubleMore, "")
14+
{
15+
return get<0>(arg) > get<1>(arg);
16+
}
17+
18+
/*
19+
* For Lobatto nodes, the resulting method should of order 2*M-2 with M=number of nodes
20+
* The test below verifies that the code approximately (up to a safety factor) reproduces
21+
* the theoretically expected rate of convergence
22+
*/
23+
TEST(ConvergenceTest, ScalarSDC)
24+
{
25+
26+
const complex<double> lambda = complex<double>(-1.0, 1.0);
27+
const double Tend = 4.0;
28+
const vector<int> nsteps = { 2, 5, 10, 15, 20 };
29+
int nsteps_l = nsteps.size();
30+
31+
vector<double> err(nsteps.size());
32+
vector<double> convrate(nsteps.size()-1);
33+
vector<double> expected_cr(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 ( int 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+
int niters = 2*nnodes-2;
45+
46+
for ( int 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 (int 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+
// The expected convergence rate for Lobatto nodes is 2*nnodes-2, but because
56+
// it will typically be not matched exactly, put in a security factor
57+
expected_cr[i] = 0.9*double(2*nnodes-2);
58+
}
59+
60+
// NOTE: There is probably a much more elegant way to test this, because
61+
// expected_cr contains the same value in all entries. But I could not so far figure
62+
// out how to build a more clever MATCHER here so far....
63+
EXPECT_THAT(convrate, testing::Pointwise(DoubleMore(), expected_cr ));
64+
65+
}
66+
}
67+
1268
int main(int argc, char** argv)
1369
{
1470
testing::InitGoogleTest(&argc, argv);

0 commit comments

Comments
 (0)