testODEIntegrator.cc
Go to the documentation of this file.
1 
11 #include <iostream>
12 #include <cmath>
13 
14 #include <utl/RK4ODEIntegrator.h>
15 #include <utl/RK5ODEIntegrator.h>
16 #include <utl/SVector.h>
17 
18 #include <tst/Verify.h>
19 #include <cppunit/extensions/HelperMacros.h>
20 
21 using namespace std;
22 using namespace utl;
23 using namespace tst;
24 
25 #define ASSERT_CLOSE(x, y) CPPUNIT_ASSERT(Verify<CloseTo>(x, y))
26 #define ASSERT_CLOSE_EPS(x, y, eps) CPPUNIT_ASSERT(Verify<CloseTo>(x, y, eps))
27 #define ASSERT_EQUAL(x, y) CPPUNIT_ASSERT(Verify<Equal>(x, y))
28 
29 
30 class HarmonicOscillator {
31 public:
32  HarmonicOscillator(const double m, const double k) : fM(m), fK(k) { }
33 
35  template<typename Vector>
36  bool
37  operator()(const double /*x*/, const Vector& y, Vector& dYdX)
38  const
39  {
40  // m \ddot{x} = -k x
41  // y_0 = x
42  // y_1 = p
43  dYdX[0] = y[1] / fM;
44  dYdX[1] = -fK * y[0];
45  return true;
46  }
47 
49  operator unsigned int() const { return 2; }
50 
51 private:
52  const double fM;
53  const double fK;
54 };
55 
56 
60 class TestODEIntegrator : public CppUnit::TestFixture {
61 
62  CPPUNIT_TEST_SUITE(TestODEIntegrator);
63  CPPUNIT_TEST(TestRK4);
64  CPPUNIT_TEST(TestRK4SVector);
65  CPPUNIT_TEST(TestRK5);
66  CPPUNIT_TEST(TestRK5SVector);
67  CPPUNIT_TEST(TestAdaptiveRK5);
68  CPPUNIT_TEST_SUITE_END();
69 
70 public:
71  void
73  {
74  typedef double Vector[2];
75 
76  const double x0 = 0;
77  const double x1 = 100;
78  const double dx = 0.1;
79  const Vector y0 = { 1, 0 };
80 
81  const double m = 1;
82  const double k = 1;
83  HarmonicOscillator ho(m, k);
84 
86 
88 
89  const double omega = sqrt(k/m);
90 
91  const double eps = 1e-4;
92 
93  double x = x0;
94 
95  for ( ; it.GetX() < x1; it += dx) {
96  ASSERT_CLOSE(it.GetX(), x);
97  ASSERT_CLOSE_EPS(it.GetY()[0], y0[0] * cos(omega * it.GetX()), eps);
98  ASSERT_CLOSE_EPS(it.GetY()[1], -y0[0] * sin(omega * it.GetX()), eps);
99 
100  x += dx;
101  }
102  }
103 
104  void
106  {
107  const double x0 = 0;
108  const double x1 = 100;
109  const double dx = 0.1;
110  const double t[2] = { 1, 0 };
111  const SVector<2> y0(t);
112 
113  const double m = 1;
114  const double k = 1;
115  HarmonicOscillator ho(m, k);
116 
118 
120 
121  const double omega = sqrt(k/m);
122 
123  const double eps = 1e-4;
124 
125  double x = x0;
126 
127  for ( ; it.GetX() < x1; it += dx) {
128  ASSERT_CLOSE(it.GetX(), x);
129  ASSERT_CLOSE_EPS(it.GetY()[0], y0[0] * cos(omega * it.GetX()), eps);
130  ASSERT_CLOSE_EPS(it.GetY()[1], -y0[0] * sin(omega * it.GetX()), eps);
131 
132  x += dx;
133  }
134  }
135 
136  void
138  {
139  typedef double Vector[2];
140 
141  const double x0 = 0;
142  const double x1 = 100;
143  const double dx = 0.1;
144  const Vector y0 = { 1, 0 };
145 
146  const double m = 1;
147  const double k = 1;
148  HarmonicOscillator ho(m, k);
149 
151 
153 
154  const double omega = sqrt(k/m);
155 
156  const double eps = 1e-6;
157 
158  double x = x0;
159 
160  for ( ; it.GetX() < x1; it += dx) {
161  ASSERT_CLOSE(it.GetX(), x);
162  ASSERT_CLOSE_EPS(it.GetY()[0], y0[0] * cos(omega * it.GetX()), eps);
163  ASSERT_CLOSE_EPS(it.GetY()[1], -y0[0] * sin(omega * it.GetX()), eps);
164 
165  x += dx;
166  }
167  }
168 
169  void
171  {
172  const double x0 = 0;
173  const double x1 = 100;
174  const double dx = 0.1;
175  const double t[2] = { 1, 0 };
176  const SVector<2> y0(t);
177 
178  const double m = 1;
179  const double k = 1;
180  HarmonicOscillator ho(m, k);
181 
183 
185 
186  const double omega = sqrt(k/m);
187 
188  const double eps = 1e-6;
189 
190  double x = x0;
191 
192  for ( ; it.GetX() < x1; it += dx) {
193  ASSERT_CLOSE(it.GetX(), x);
194  ASSERT_CLOSE_EPS(it.GetY()[0], y0[0] * cos(omega * it.GetX()), eps);
195  ASSERT_CLOSE_EPS(it.GetY()[1], -y0[0] * sin(omega * it.GetX()), eps);
196 
197  x += dx;
198  }
199  }
200 
201  void
203  {
204  typedef double Vector[2];
205 
206  const double x0 = 0;
207  const double x1 = 100;
208  const double dx = 0.1;
209  const Vector y0 = { 1, 0 };
210 
211  const double m = 1;
212  const double k = 1;
213  HarmonicOscillator ho(m, k);
214 
216 
217  const double accuracy = 1e-5;
218 
220  rk5.AdaptiveBegin(x0, dx, y0, accuracy);
221 
222  const double omega = sqrt(k/m);
223 
224  const double eps = 1e-3;
225 
226  // try first with step dx
227  // if step is too large, a smaller one gets calcualted
228  // but never larger
229  int count = 0;
230  for ( ; it.GetX() < x1; it += dx) {
231  const double x = it.GetX();
232  ASSERT_CLOSE_EPS(it.GetY()[0], y0[0] * cos(omega * x), eps);
233  ASSERT_CLOSE_EPS(it.GetY()[1], -y0[0] * sin(omega * x), eps);
234 
235  ++count;
236  }
237 
238  cout << "\nRK5 +=: " << count << endl;
239 
241  rk5.AdaptiveBegin(x0, dx, y0, accuracy);
242 
243  // run all the time with optimal step which can become
244  // larger than the initial dx
245  count = 0;
246  for ( ; it2.GetX() < x1; ++it2) {
247  const double x = it2.GetX();
248  ASSERT_CLOSE_EPS(it2.GetY()[0], y0[0] * cos(omega * x), eps);
249  ASSERT_CLOSE_EPS(it2.GetY()[1], -y0[0] * sin(omega * x), eps);
250 
251  ++count;
252  }
253 
254  cout << "RK5 ++: " << count << endl;
255  }
256 
257 };
258 
259 
bool operator()(const double, const Vector &y, Vector &dYdX) const
calculate derivatives
#define ASSERT_CLOSE_EPS(x, y, eps)
VectorType & GetY()
RK5Iterator< DerivativeFunctor, VectorType > Begin(const double x, const VectorType &y)
RK4Iterator< DerivativeFunctor, VectorType > Begin(const double x, const VectorType &y)
double GetX() const
HarmonicOscillator(const double m, const double k)
CPPUNIT_TEST_SUITE_REGISTRATION(testAiresShowerFile)
double GetX() const
VectorType & GetY()
Static (small and dense) vector class.
Definition: SVector.h:33
double eps
#define ASSERT_CLOSE(x, y)
AdaptiveRK5Iterator< DerivativeFunctor, VectorType > AdaptiveBegin(const double x, const double dx, const VectorType &y, const double accuracy=1e-5)
Vector object.
Definition: Vector.h:30
constexpr double m
Definition: AugerUnits.h:121

, generated on Tue Sep 26 2023.