Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
blochoscillations2d.cpp
Go to the documentation of this file.
1/**
2 * @file blochoscillations2d.cpp
3 * @brief Implements the blochoscillations2d physics/numerical component used by QPE experiments.
4 * @ingroup qpe_quantum
5 *
6 * Source: @c core/quantum/blochoscillations2d.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
12#include "blochoscillations2d.h"
13
14#include <algorithm>
15#include <cmath>
16#include <vector>
17
18namespace qpe {
19namespace {
20
21constexpr double kPi = 3.141592653589793238462643383279502884;
22
23/**
24 * @brief Performs near.
25 * @param a The a value used by the operation.
26 * @param b The b value used by the operation.
27 * @param scale The scale value used by the operation.
28 */
29bool near(double a, double b, double scale = 1.0) noexcept
30{
31 const double tolerance = 1.0e-4 * std::max(1.0, scale);
32 return std::fabs(a - b) <= tolerance;
33}
34
35/**
36 * @brief Performs fail.
37 * @param reason The reason value used by the operation.
38 * @param message The message value used by the operation.
39 */
40void fail(std::string *reason, const char *message) noexcept
41{
42 if (reason) {
43 *reason = message;
44 }
45}
46
47} // namespace
48
50 BlochLatticeGeometry2D &geometry,
51 std::string *reason) noexcept
52{
53 geometry = BlochLatticeGeometry2D();
54 if (reason) reason->clear();
55
56 std::vector<const PotentialObject2D *> wells;
57 const PotentialObject2D *linear = nullptr;
58
59 for (const PotentialObject2D &object : scene.objects()) {
60 if (!object.enabled) continue;
61
62 if (object.type == PotentialObjectType2D::Rectangle && object.value < 0.0f) {
63 wells.push_back(&object);
64 continue;
65 }
66
67 if (object.type == PotentialObjectType2D::Linear) {
68 if (linear != nullptr) {
69 fail(reason, "Bloch lattice expects exactly one enabled Linear force term.");
70 return false;
71 }
72 linear = &object;
73 continue;
74 }
75
76 fail(reason, "Bloch lattice accepts only negative Rectangle wells plus one Linear X term.");
77 return false;
78 }
79
80 if (wells.size() < 5u) {
81 fail(reason, "Bloch lattice needs at least five enabled periodic wells.");
82 return false;
83 }
84 if (linear == nullptr || std::fabs(static_cast<double>(linear->slopeX)) <= 1.0e-12 ||
85 std::fabs(static_cast<double>(linear->slopeY)) > 1.0e-9) {
86 fail(reason, "Bloch lattice needs one non-zero Linear slopeX and zero slopeY.");
87 return false;
88 }
89
90 std::sort(wells.begin(), wells.end(),
91 [](const PotentialObject2D *a, const PotentialObject2D *b) {
92 return a->centerX < b->centerX;
93 });
94
95 const PotentialObject2D &first = *wells.front();
96 const double spacing = static_cast<double>(wells[1]->centerX - wells[0]->centerX);
97 if (!(spacing > 0.0) || !std::isfinite(spacing)) {
98 fail(reason, "Bloch lattice spacing is invalid.");
99 return false;
100 }
101
102 for (std::size_t i = 0u; i < wells.size(); ++i) {
103 const PotentialObject2D &well = *wells[i];
104 if (!near(well.value, first.value, std::fabs(first.value)) ||
105 !near(well.width, first.width, first.width) ||
106 !near(well.height, first.height, first.height) ||
107 !near(well.centerY, first.centerY, std::max(1.0f, std::fabs(first.centerY)))) {
108 fail(reason, "Bloch lattice wells must have equal depth, width, height and centerY.");
109 return false;
110 }
111 if (i > 0u) {
112 const double localSpacing = static_cast<double>(wells[i]->centerX - wells[i - 1u]->centerX);
113 if (!near(localSpacing, spacing, spacing)) {
114 fail(reason, "Bloch lattice wells are not equally spaced.");
115 return false;
116 }
117 }
118 }
119
120 geometry.valid = true;
121 geometry.spacing = spacing;
122 geometry.wellWidth = first.width;
123 geometry.wellDepth = -static_cast<double>(first.value);
124 geometry.slopeX = linear->slopeX;
125 geometry.forceX = -static_cast<double>(linear->slopeX);
126 geometry.firstCenterX = wells.front()->centerX;
127 geometry.lastCenterX = wells.back()->centerX;
128 geometry.wellCount = static_cast<int>(wells.size());
129 return true;
130}
131
133 double hbar) noexcept
134{
135 if (!geometry.valid || !(geometry.spacing > 0.0) || !(hbar > 0.0) ||
136 !std::isfinite(hbar) || !std::isfinite(geometry.forceX) ||
137 std::fabs(geometry.forceX) <= 1.0e-15) {
138 return 0.0;
139 }
140 return 2.0 * kPi * hbar /
141 (std::fabs(geometry.forceX) * geometry.spacing);
142}
143
145 double hbar) noexcept
146{
147 if (!geometry.valid || !(geometry.spacing > 0.0) || !(hbar > 0.0) ||
148 !std::isfinite(hbar)) {
149 return 0.0;
150 }
151 return kPi * hbar / geometry.spacing;
152}
153
155 double initialMomentum,
156 double time,
157 double hbar) noexcept
158{
159 const double edge = zoneEdgeMomentum(geometry, hbar);
160 if (!(edge > 0.0) || !std::isfinite(initialMomentum) || !std::isfinite(time)) {
161 return 0.0;
162 }
163
164 // dp/dt = F. One reciprocal-lattice period in physical momentum is 2*edge.
165 const double raw = initialMomentum + geometry.forceX * time;
166 const double width = 2.0 * edge;
167 double wrapped = std::fmod(raw + edge, width);
168 if (wrapped < 0.0) wrapped += width;
169 return wrapped - edge;
170}
171
172} // namespace qpe
Declares the blochoscillations2d physics/numerical component used by QPE experiments.
static bool identify(const PotentialScene2D &scene, BlochLatticeGeometry2D &geometry, std::string *reason=nullptr) noexcept
Returns identify.
static double reducedZoneMomentum(const BlochLatticeGeometry2D &geometry, double initialMomentum, double time, double hbar=1.0) noexcept
Performs reduced zone momentum.
static double zoneEdgeMomentum(const BlochLatticeGeometry2D &geometry, double hbar=1.0) noexcept
Performs zone edge momentum.
static double blochPeriod(const BlochLatticeGeometry2D &geometry, double hbar=1.0) noexcept
Performs bloch period.
Implements the Potential Scene2D component.
bool near(double a, double b, double scale=1.0) noexcept
Performs near.
Data structure used by the Bloch Lattice Geometry2D component.
Data structure used by the Potential Object2D component.