29void fail(std::string *reason,
const char *message)
noexcept
31 if (reason) *reason = message;
49 std::string *reason)
noexcept
52 if (reason) reason->clear();
57 if (!
object.enabled)
continue;
59 object.width > 4.0f *
object.height) {
60 if (floor !=
nullptr) {
61 fail(reason,
"Quantum bouncer expects exactly one horizontal positive Rectangle floor.");
66 std::fabs(
object.slopeX) < 1.0e-7f &&
object.slopeY > 0.0f) {
67 if (linear !=
nullptr) {
68 fail(reason,
"Quantum bouncer expects exactly one downward Linear-Y force term.");
73 fail(reason,
"Quantum bouncer scene must contain only one floor Rectangle and one Linear-Y term.");
78 if (floor ==
nullptr || linear ==
nullptr) {
79 fail(reason,
"Quantum bouncer requires one floor Rectangle and one positive Linear-Y slope.");
83 geometry.
valid =
true;
84 geometry.floorY =
static_cast<double>(floor->
centerY) + 0.5 * floor->
height;
85 geometry.floorPotential = floor->
value;
86 geometry.force = linear->
slopeY;
94 if (!geometry.valid || !(geometry.force > 0.0) || !(mass > 0.0) || !(hbar > 0.0) ||
95 !std::isfinite(mass) || !std::isfinite(hbar)) {
98 return std::cbrt((hbar * hbar) / (2.0 * mass * geometry.force));
104 double hbar)
noexcept
106 if (stateIndex < 0 || stateIndex >=
static_cast<int>(
sizeof(kAiryZeros) /
sizeof(kAiryZeros[0]))) {
109 const double ell = airyLength(geometry, mass, hbar);
110 return ell > 0.0 ? geometry.force * ell * kAiryZeros[stateIndex] : 0.0;
116 double hbar)
noexcept
118 const double ell = airyLength(geometry, mass, hbar);
119 if (!(ell > 0.0) || stateIndex < 0 ||
120 stateIndex >=
static_cast<int>(
sizeof(kAiryZeros) /
sizeof(kAiryZeros[0]))) {
121 return geometry.floorY;
123 return geometry.floorY + ell * kAiryZeros[stateIndex];
128 std::vector<float> result(field.
height(), 0.0f);
129 if (field.
empty())
return result;
131 const double dx =
static_cast<double>(field.
dx());
132 for (std::size_t y = 0u; y < field.
height(); ++y) {
134 for (std::size_t x = 0u; x < field.
width(); ++x) {
136 const double re = value.real();
137 const double im = value.imag();
138 sum += re * re + im * im;
140 result[y] =
static_cast<float>(sum * dx);
147 double bandHeight)
noexcept
149 if (field.empty() || !geometry.valid || !(bandHeight > 0.0))
return 0.0;
150 const double cellArea =
static_cast<double>(field.dx()) * field.dy();
151 double probability = 0.0;
152 for (std::size_t y = 0u; y < field.height(); ++y) {
154 if (py < geometry.floorY || py > geometry.floorY + bandHeight)
continue;
155 for (std::size_t x = 0u; x < field.width(); ++x) {
157 probability += (
static_cast<double>(value.real()) * value.real() +
158 static_cast<double>(value.imag()) * value.imag()) * cellArea;
168 double initialMomentumY)
noexcept
170 if (!geometry.valid || !(geometry.force > 0.0) || !(mass > 0.0) || !(time >= 0.0)) {
174 const double a = geometry.force / mass;
175 double y = std::max(initialY, geometry.floorY);
176 double v = initialMomentumY / mass;
177 double remaining = time;
179 for (
int impact = 0; impact < 128 && remaining > 1.0e-12; ++impact) {
180 const double height = std::max(0.0, y - geometry.floorY);
181 const double discriminant = std::max(0.0, v * v + 2.0 * a * height);
182 const double hit = (v + std::sqrt(discriminant)) / a;
183 if (!(hit > 1.0e-12) || hit > remaining) {
184 return std::max(geometry.floorY, y + v * remaining - 0.5 * a * remaining * remaining);
190 return std::max(geometry.floorY, y);
194 : maximumSamples_(maximumSamples > 0u ? maximumSamples : 1u)
211 double initialMomentumY)
223 if (
maximumSamples == 0u)
throw std::invalid_argument(
"QuantumBouncerHistory2D maximumSamples must be > 0");
229 double mass,
double hbar)
231 if (!
configured() || field.
empty() || !(mass > 0.0) || !(hbar > 0.0))
return false;
235 sample.meanY = spatial.
meanY;
236 sample.sigmaY = spatial.
sigmaY;
237 sample.norm = spatial.
norm2;
Owning Cartesian grid of complex scalar samples.
bool empty() const noexcept
Returns whether the field contains no samples.
float dx() const noexcept
Returns the X grid spacing.
std::size_t height() const noexcept
Returns the number of samples along Y.
std::complex< float > Value
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.
Implements the Potential Scene2D component.
static bool identify(const PotentialScene2D &scene, QuantumBouncerGeometry2D &geometry, std::string *reason=nullptr) noexcept
Returns identify.
static double probabilityNearFloor(const ComplexField2D &field, const QuantumBouncerGeometry2D &geometry, double bandHeight) noexcept
Returns probability near floor.
static double airyEnergy(int stateIndex, const QuantumBouncerGeometry2D &geometry, double mass, double hbar) noexcept
Performs airy energy.
static double airyTurningHeight(int stateIndex, const QuantumBouncerGeometry2D &geometry, double mass, double hbar) noexcept
Performs airy turning height.
static double classicalHeight(double time, const QuantumBouncerGeometry2D &geometry, double mass, double initialY, double initialMomentumY) noexcept
Performs classical height.
static double airyLength(const QuantumBouncerGeometry2D &geometry, double mass, double hbar) noexcept
Performs airy length.
static std::vector< float > marginalProbabilityY(const ComplexField2D &field)
Performs marginal probability y.
void trimToLimit()
Carries out trim to limit.
void clear() noexcept
Clears stored state and returns the component to its empty/default state.
const QuantumBouncerGeometry2D & geometry() const noexcept
Carries out geometry.
bool configure(const QuantumBouncerGeometry2D &geometry, double initialY, double initialMomentumY)
Returns configure.
QuantumBouncerHistory2D(std::size_t maximumSamples=1200u)
Constructs a Quantum Bouncer History 2D instance.
bool append(double time, const ComplexField2D &field, double mass, double hbar)
Carries out append.
bool configured() const noexcept
Returns configured.
QuantumBouncerGeometry2D geometry_
double initialMomentumY() const noexcept
Initializes ial momentum y.
std::size_t maximumSamples() const noexcept
Carries out maximum samples.
std::size_t maximumSamples_
double initialY() const noexcept
Initializes ial y.
void setMaximumSamples(std::size_t maximumSamples)
Sets maximum samples.
std::vector< QuantumBouncerSample2D > samples_
static SpatialObservables2D spatial(const ComplexField2D &field) noexcept
Performs spatial.
Declares the gaussianpacket2d physics/numerical component used by QPE experiments.
const double kAiryZeros[]
Declares the quantumbouncer2d physics/numerical component used by QPE experiments.
Data structure used by the Potential Object2D component.
bool valid() const noexcept
Performs valid.
Data structure used by the Quantum Bouncer Geometry2D component.
Data structure used by the Quantum Bouncer Sample2D component.
Data structure used by the Spatial Observables2D component.
Declares the wavepacketobservables2d physics/numerical component used by QPE experiments.