27bool finite(
double value)
noexcept
29 return std::isfinite(value);
37void fail(
const char **reason,
const char *message)
noexcept
39 if (reason) *reason = message;
49 return !a.empty() && !b.empty() &&
50 a.width() == b.width() && a.height() == b.height() &&
51 a.dx() == b.dx() && a.dy() == b.dy();
57 const char **reason)
noexcept
59 if (!config.enabled)
return true;
60 if (!(config.reversalTime > 0.0) || !finite(config.reversalTime)) {
61 fail(reason,
"Loschmidt reversal time must be finite and positive.");
64 if (!finite(config.momentumErrorX) || !finite(config.momentumErrorY)) {
65 fail(reason,
"Loschmidt momentum-error values must be finite.");
68 if (std::fabs(config.momentumErrorX) > 1000.0 ||
69 std::fabs(config.momentumErrorY) > 1000.0) {
70 fail(reason,
"Loschmidt momentum-error values are unreasonably large.");
80 if (field.empty() || !(hbar > 0.0) || !finite(hbar) ||
81 !validateConfig(config,
nullptr)) {
85 const double invHbar = 1.0 / hbar;
86 for (std::size_t y = 0; y < field.height(); ++y) {
88 for (std::size_t x = 0; x < field.width(); ++x) {
90 const std::complex<float> reversed = std::conj(field(x, y));
92 (config.momentumErrorX * px + config.momentumErrorY * py) * invHbar;
93 const std::complex<float> kick(
94 static_cast<float>(std::cos(phase)),
95 static_cast<float>(std::sin(phase)));
96 field(x, y) = reversed * kick;
99 return field.normalize();
105 if (!sameGrid(reference, field))
return 0.0;
109 std::complex<double> overlap(0.0, 0.0);
110 double normReference = 0.0;
111 double normField = 0.0;
112 const double cell =
static_cast<double>(field.dx()) *
static_cast<double>(field.dy());
114 for (std::size_t i = 0; i < field.size(); ++i) {
115 const std::complex<double> a(reference.data()[i].real(), reference.data()[i].imag());
116 const std::complex<double> b(field.data()[i].real(), field.data()[i].imag());
118 normReference += std::norm(a);
119 normField += std::norm(b);
121 normReference *= cell;
124 const double denom = normReference * normField;
125 if (!(denom > 0.0) || !finite(denom))
return 0.0;
126 const double f = std::norm(overlap) / denom;
127 return std::max(0.0, std::min(1.0, f));
133 if (!sameGrid(reference, field))
return 0.0;
136 double normReference = 0.0;
137 double normField = 0.0;
138 const double cell =
static_cast<double>(field.dx()) *
static_cast<double>(field.dy());
139 for (std::size_t i = 0; i < field.size(); ++i) {
140 const double pa =
static_cast<double>(std::norm(reference.data()[i]));
141 const double pb =
static_cast<double>(std::norm(field.data()[i]));
142 bc += std::sqrt(std::max(0.0, pa * pb));
147 normReference *= cell;
149 const double denom = normReference * normField;
150 if (!(denom > 0.0) || !finite(denom))
return 0.0;
151 const double f = (bc * bc) / denom;
152 return std::max(0.0, std::min(1.0, f));
157 double &meanY)
noexcept
161 if (field.empty())
return false;
164 for (std::size_t y = 0; y < field.height(); ++y) {
166 for (std::size_t x = 0; x < field.width(); ++x) {
168 const double p =
static_cast<double>(std::norm(field(x, y)));
174 if (!(weight > 0.0) || !finite(weight)) {
181 return finite(meanX) && finite(meanY);
185 : maximumSamples_(std::max<std::size_t>(2u, maximumSamples))
212 bool reversalApplied)
220 sample.norm = field.
norm2();
221 sample.reversalApplied = reversalApplied;
227 const double storeInterval = totalWindow /
229 const bool first =
samples_.empty();
230 const bool reversalEdge = reversalApplied &&
232 const bool intervalElapsed =
samples_.empty() ||
233 time -
samples_.back().time >= std::max(1.0e-9, storeInterval) - 1.0e-12;
234 if (first || reversalEdge || intervalElapsed) {
Owning Cartesian grid of complex scalar samples.
double norm2() const noexcept
Returns the discrete integral of |psi|^2 including dx*dy.
bool empty() const noexcept
Returns whether the field contains no samples.
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 double stateEchoFidelity(const ComplexField2D &reference, const ComplexField2D &field) noexcept
Performs state echo fidelity.
static bool validateConfig(const QuantumLoschmidt2DConfig &config, const char **reason=nullptr) noexcept
Validates config.
static bool centroid(const ComplexField2D &field, double &meanX, double &meanY) noexcept
Performs centroid.
static bool applyTimeReversal(ComplexField2D &field, const QuantumLoschmidt2DConfig &config, double hbar) noexcept
Applies time reversal.
static double densityEchoFidelity(const ComplexField2D &reference, const ComplexField2D &field) noexcept
Performs density echo fidelity.
bool append(double time, const ComplexField2D &field, bool reversalApplied)
Carries out append.
std::vector< QuantumLoschmidtSample2D > samples_
std::size_t maximumSamples_
bool configure(const ComplexField2D &reference, const QuantumLoschmidt2DConfig &config)
Returns configure.
QuantumLoschmidt2DConfig config_
QuantumLoschmidtHistory2D(std::size_t maximumSamples=1600u)
Constructs a Quantum Loschmidt History 2D instance.
const QuantumLoschmidt2DConfig & config() const noexcept
Returns config.
ComplexField2D reference_
void trimToLimit()
Carries out trim to limit.
void clear() noexcept
Clears stored state and returns the component to its empty/default state.
Declares the gaussianpacket2d physics/numerical component used by QPE experiments.
Declares the quantumloschmidt2d physics/numerical component used by QPE experiments.
Configuration values for Quantum Loschmidt2D Config.
Data structure used by the Quantum Loschmidt Sample2D component.