35 if (!(hbar > 0.0f) || !std::isfinite(
static_cast<double>(hbar))) {
36 throw std::invalid_argument(
"ProbabilityCurrent2D: hbar must be finite and positive");
38 if (!(mass > 0.0f) || !std::isfinite(
static_cast<double>(mass))) {
39 throw std::invalid_argument(
"ProbabilityCurrent2D: mass must be finite and positive");
47 out.
jx.assign(field.
size(), 0.0f);
48 out.
jy.assign(field.
size(), 0.0f);
54 const double inv2Dx = 1.0 / (2.0 *
static_cast<double>(field.
dx()));
55 const double inv2Dy = 1.0 / (2.0 *
static_cast<double>(field.
dy()));
56 const double prefactor =
static_cast<double>(hbar) /
static_cast<double>(mass);
57 const double cellArea =
static_cast<double>(field.
dx()) *
static_cast<double>(field.
dy());
59 for (std::size_t y = 1; y + 1 < field.
height(); ++y) {
60 for (std::size_t x = 1; x + 1 < field.
width(); ++x) {
61 const std::complex<double> psi(
62 static_cast<double>(field(x, y).real()),
63 static_cast<double>(field(x, y).imag()));
65 const std::complex<double> psiXp(
66 static_cast<double>(field(x + 1, y).real()),
67 static_cast<double>(field(x + 1, y).imag()));
68 const std::complex<double> psiXm(
69 static_cast<double>(field(x - 1, y).real()),
70 static_cast<double>(field(x - 1, y).imag()));
71 const std::complex<double> psiYp(
72 static_cast<double>(field(x, y + 1).real()),
73 static_cast<double>(field(x, y + 1).imag()));
74 const std::complex<double> psiYm(
75 static_cast<double>(field(x, y - 1).real()),
76 static_cast<double>(field(x, y - 1).imag()));
78 const std::complex<double> dPsiDx = (psiXp - psiXm) * inv2Dx;
79 const std::complex<double> dPsiDy = (psiYp - psiYm) * inv2Dy;
81 const double currentX = prefactor * std::imag(std::conj(psi) * dPsiDx);
82 const double currentY = prefactor * std::imag(std::conj(psi) * dPsiDy);
83 const std::size_t index = y * field.
width() + x;
85 out.
jx[index] =
static_cast<float>(currentX);
86 out.
jy[index] =
static_cast<float>(currentY);
88 const float magnitude =
static_cast<float>(std::sqrt(currentX * currentX + currentY * currentY));
104 if (!(hbar > 0.0f) || !std::isfinite(
static_cast<double>(hbar)))
105 throw std::invalid_argument(
"ProbabilityCurrent2D: hbar must be finite and positive");
106 if (!(mass > 0.0f) || !std::isfinite(
static_cast<double>(mass)))
107 throw std::invalid_argument(
"ProbabilityCurrent2D: mass must be finite and positive");
109 throw std::invalid_argument(
"ProbabilityCurrent2D: gauge field does not match wavefunction grid");
113 out.
dx = field.
dx(); out.
dy = field.
dy();
114 out.
jx.assign(field.
size(), 0.0f); out.
jy.assign(field.
size(), 0.0f);
115 if (field.
width() < 3 || field.
height() < 3)
return out;
117 const double inv2Dx = 1.0 / (2.0 *
static_cast<double>(field.
dx()));
118 const double inv2Dy = 1.0 / (2.0 *
static_cast<double>(field.
dy()));
119 const double prefactor =
static_cast<double>(hbar) /
static_cast<double>(mass);
120 const double cellArea =
static_cast<double>(field.
dx()) *
static_cast<double>(field.
dy());
122 for (std::size_t y = 1; y + 1 < field.
height(); ++y) {
123 for (std::size_t x = 1; x + 1 < field.
width(); ++x) {
124 const std::complex<double> psi(field(x, y));
125 const std::complex<double> right = std::complex<double>(gauge.
linkX(x, y)) *
126 std::complex<double>(field(x + 1u, y));
127 const std::complex<double> left = std::conj(std::complex<double>(gauge.
linkX(x - 1u, y))) *
128 std::complex<double>(field(x - 1u, y));
129 const std::complex<double> up = std::complex<double>(gauge.
linkY(x, y)) *
130 std::complex<double>(field(x, y + 1u));
131 const std::complex<double> down = std::conj(std::complex<double>(gauge.
linkY(x, y - 1u))) *
132 std::complex<double>(field(x, y - 1u));
133 const std::complex<double> dPsiDx = (right - left) * inv2Dx;
134 const std::complex<double> dPsiDy = (up - down) * inv2Dy;
135 const double currentX = prefactor * std::imag(std::conj(psi) * dPsiDx);
136 const double currentY = prefactor * std::imag(std::conj(psi) * dPsiDy);
137 const std::size_t index = y * field.
width() + x;
138 out.
jx[index] =
static_cast<float>(currentX);
139 out.
jy[index] =
static_cast<float>(currentY);
141 static_cast<float>(std::sqrt(currentX * currentX + currentY * currentY)));