Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
gaussianpacket2d_tests.cpp
Go to the documentation of this file.
1/**
2 * @file gaussianpacket2d_tests.cpp
3 * @brief Implements regression and invariant tests for gaussianpacket2d tests.
4 * @ingroup qpe_tests
5 *
6 * Source: @c tests/gaussianpacket2d_tests.cpp. This file is part of Quantum Phenomena Explorer (QPE),
7 * maintained by Officina Turini. See LICENSE_IT.txt / LICENSE.txt for the
8 * QPE freeware source-available terms and THIRD_PARTY_NOTICES.txt for
9 * third-party components.
10 */
11
13
16
17#include <cmath>
18#include <complex>
19#include <stdexcept>
20
21namespace qpe {
22namespace tests {
23namespace {
24
25/**
26 * @brief Performs nearly equal.
27 * @param a The a value used by the operation.
28 * @param b The b value used by the operation.
29 * @param tolerance The tolerance value used by the operation.
30 */
31bool nearlyEqual(double a, double b, double tolerance)
32{
33 return std::abs(a - b) <= tolerance;
34}
35
36/**
37 * @brief Performs fail.
38 * @param errorMessage The error message value used by the operation.
39 * @param message The message value used by the operation.
40 */
41bool fail(std::string &errorMessage, const char *message)
42{
43 errorMessage = message;
44 return false;
45}
46
47/**
48 * @brief Performs wrapped angle difference.
49 * @param a The a value used by the operation.
50 * @param b The b value used by the operation.
51 */
52double wrappedAngleDifference(double a, double b)
53{
54 const double pi = 3.14159265358979323846;
55 double d = a - b;
56 while (d > pi) d -= 2.0 * pi;
57 while (d < -pi) d += 2.0 * pi;
58 return d;
59}
60
61} // namespace
62
63/**
64 * @brief Runs gaussian packet2 d tests.
65 * @param errorMessage The error message value used by the operation.
66 */
67bool runGaussianPacket2DTests(std::string &errorMessage)
68{
69 errorMessage.clear();
70
71 try {
72 // Odd dimensions put an actual sample at x=y=0 and make the
73 // expectation-value checks straightforward.
74 ComplexField2D field(257, 257, 0.05f, 0.05f);
75
77 p.centerX = -1.25f;
78 p.centerY = 0.70f;
79 p.sigma = 0.60f;
80 p.momentumX = 2.10f;
81 p.momentumY = -0.80f;
82 p.hbar = 1.0f;
83
85
86 if (!nearlyEqual(field.norm2(), 1.0, 5.0e-6)) {
87 return fail(errorMessage, "Gaussian packet is not normalized");
88 }
89
90 double meanX = 0.0;
91 double meanY = 0.0;
92 double meanX2 = 0.0;
93 double meanY2 = 0.0;
94 const double cellArea = static_cast<double>(field.dx()) *
95 static_cast<double>(field.dy());
96
97 for (std::size_t y = 0; y < field.height(); ++y) {
98 const double yy = GaussianPacket2D::yCoordinate(field, y);
99 for (std::size_t x = 0; x < field.width(); ++x) {
100 const double xx = GaussianPacket2D::xCoordinate(field, x);
101 const double probability = static_cast<double>(std::norm(field(x, y)));
102 const double w = probability * cellArea;
103
104 meanX += xx * w;
105 meanY += yy * w;
106 meanX2 += xx * xx * w;
107 meanY2 += yy * yy * w;
108 }
109 }
110
111 if (!nearlyEqual(meanX, p.centerX, 2.0e-3) ||
112 !nearlyEqual(meanY, p.centerY, 2.0e-3)) {
113 return fail(errorMessage, "Gaussian packet centre is incorrect");
114 }
115
116 const double varX = meanX2 - meanX * meanX;
117 const double varY = meanY2 - meanY * meanY;
118 const double expectedVariance = static_cast<double>(p.sigma) * p.sigma;
119
120 if (!nearlyEqual(varX, expectedVariance, 3.0e-3) ||
121 !nearlyEqual(varY, expectedVariance, 3.0e-3)) {
122 return fail(errorMessage, "Gaussian packet sigma is incorrect");
123 }
124
125 // Check that the phase increment along X is p_x * dx / hbar.
126 const std::size_t cx = field.width() / 2;
127 const std::size_t cy = field.height() / 2;
128 const std::complex<float> a = field(cx, cy);
129 const std::complex<float> b = field(cx + 1, cy);
130 const double measuredPhaseStep = std::arg(b * std::conj(a));
131 const double expectedPhaseStep =
132 static_cast<double>(p.momentumX) * field.dx() / p.hbar;
133
134 if (std::abs(wrappedAngleDifference(measuredPhaseStep, expectedPhaseStep)) > 2.0e-5) {
135 return fail(errorMessage, "Gaussian packet X phase gradient is incorrect");
136 }
137
138 // Step 7.2 also exposes py, so verify the independent Y phase gradient.
139 const std::complex<float> c = field(cx, cy + 1);
140 const double measuredPhaseStepY = std::arg(c * std::conj(a));
141 const double expectedPhaseStepY =
142 static_cast<double>(p.momentumY) * field.dy() / p.hbar;
143
144 if (std::abs(wrappedAngleDifference(measuredPhaseStepY, expectedPhaseStepY)) > 2.0e-5) {
145 return fail(errorMessage, "Gaussian packet Y phase gradient is incorrect");
146 }
147
148 bool invalidSigmaRejected = false;
149 try {
151 bad.sigma = 0.0f;
153 } catch (const std::invalid_argument &) {
154 invalidSigmaRejected = true;
155 }
156
157 if (!invalidSigmaRejected) {
158 return fail(errorMessage, "invalid sigma was not rejected");
159 }
160 } catch (const std::exception &e) {
161 errorMessage = e.what();
162 return false;
163 }
164
165 return true;
166}
167
168} // namespace tests
169} // namespace qpe
Owning Cartesian grid of complex scalar samples.
double norm2() const noexcept
Returns the discrete integral of |psi|^2 including dx*dy.
float dx() const noexcept
Returns the X grid spacing.
std::size_t height() const noexcept
Returns the number of samples along Y.
float dy() const noexcept
Returns the Y grid spacing.
std::size_t width() const noexcept
Returns the number of samples along X.
static double yCoordinate(const ComplexField2D &field, std::size_t y) noexcept
Performs y coordinate.
static double xCoordinate(const ComplexField2D &field, std::size_t x) noexcept
Performs x coordinate.
static void initialize(ComplexField2D &field, const GaussianPacket2DParams &params)
Initializes ialize.
Declares the complex scalar field container representing two-dimensional wave functions.
Declares the gaussianpacket2d physics/numerical component used by QPE experiments.
Declares regression and invariant tests for gaussianpacket2d tests.
double wrappedAngleDifference(double a, double b)
Performs wrapped angle difference.
bool runGaussianPacket2DTests(std::string &errorMessage)
Runs gaussian packet2 d tests.
Configuration values for Gaussian Packet2D Params.