62 std::vector<Real> zeros;
63 const Real scan_step = 0.05;
64 Real previous_argument = 1e-6;
67 for (
Real argument = previous_argument + scan_step;
68 zeros.size() <
static_cast<size_t>(count) && argument < 500.0;
69 argument += scan_step) {
71 if (previous_value == 0.0 || (previous_value < 0.0) != (value < 0.0)) {
72 Real low = previous_argument;
74 for (
int iteration = 0; iteration < 200; iteration++) {
75 Real middle = 0.5 * (low + high);
82 zeros.push_back(0.5 * (low + high));
84 previous_argument = argument;
85 previous_value = value;
108 Real augmentation_radius,
109 const std::vector<Real>& radial_grid,
111 std::vector<Real> shape(mesh_size, 0.0);
113 if (zeros.size() < 2 || augmentation_radius <= 0.0)
116 const Real first_argument = zeros[0] / augmentation_radius;
117 const Real second_argument = zeros[1] / augmentation_radius;
134 auto moment_of = [&](
Real wavenumber) {
135 return std::pow(augmentation_radius, angular_momentum + 2) *
140 Real first_moment = moment_of(first_argument);
141 Real second_moment = moment_of(second_argument);
143 angular_momentum, first_argument * augmentation_radius);
153 Real determinant = first_moment * second_slope - second_moment * first_slope;
154 if (std::abs(determinant) < 1e-30)
156 Real first_coefficient = second_slope / determinant;
157 Real second_coefficient = -first_slope / determinant;
159 for (
int point = 0; point < mesh_size; point++) {
160 Real radius = radial_grid[point];
161 if (radius > augmentation_radius)
164 first_coefficient *
spherical_bessel(angular_momentum, first_argument * radius) +
165 second_coefficient *
spherical_bessel(angular_momentum, second_argument * radius);
166 shape[point] = value * radius * radius;
181 int angular_momentum) {
182 int mesh_size = pseudopotential.
mesh_size;
183 std::vector<Real> integrand(mesh_size);
184 const auto& all_electron_first =
186 const auto& all_electron_second =
191 for (
int point = 0; point < mesh_size; point++) {
192 Real difference = all_electron_first[point] * all_electron_second[point] -
193 pseudo_first[point] * pseudo_second[point];
195 difference * std::pow(pseudopotential.
radial_grid[point], angular_momentum);
210 if (number_of_channels == 0)
213 bool already_present =
false;
215 for (
const auto& channel : pair) {
216 if (!channel.empty())
217 already_present =
true;
223 int maximum_angular_momentum = 0;
225 maximum_angular_momentum = std::max(maximum_angular_momentum, wave.angular_momentum);
226 int number_of_angular_momenta = 2 * maximum_angular_momentum + 1;
229 if (augmentation_radius <= 0.0)
233 std::vector<std::vector<Real>> shapes(number_of_angular_momenta);
234 for (
int angular_momentum = 0; angular_momentum < number_of_angular_momenta;
235 angular_momentum++) {
243 static_cast<size_t>(number_of_channels) * number_of_channels,
244 std::vector<std::vector<Real>>(number_of_angular_momenta));
247 for (
int first = 0; first < number_of_channels; first++) {
248 for (
int second = 0; second < number_of_channels; second++) {
251 size_t pair_index =
static_cast<size_t>(first) * number_of_channels + second;
253 for (
int angular_momentum = 0; angular_momentum < number_of_angular_momenta;
254 angular_momentum++) {
260 bool allowed = angular_momentum >= std::abs(first_l - second_l) &&
261 angular_momentum <= first_l + second_l &&
262 (first_l + second_l + angular_momentum) % 2 == 0;
270 destination.assign(pseudopotential.
mesh_size, 0.0);
271 for (
int point = 0; point < pseudopotential.
mesh_size; point++)
272 destination[point] = moment * shapes[angular_momentum][point];