48 Real folded_component = translation_component - std::round(translation_component);
49 Real translation_magnitude = std::abs(folded_component);
53 int fractional_denominator =
static_cast<int>(std::round(1.0 / translation_magnitude));
54 if (std::abs(translation_magnitude - 1.0 / fractional_denominator) >
58 if (fractional_denominator == 2 || fractional_denominator == 3 ||
59 fractional_denominator == 4 || fractional_denominator == 6) {
60 return fractional_denominator;
84 fft_factors[0] = fft_factors[1] = fft_factors[2] = 1;
86 const std::vector<SymmetryOperation> symmetry_operations =
89 for (
int dimension = 0; dimension < 3; dimension++) {
90 fft_factors[dimension] =
91 least_common_multiple(fft_factors[dimension],
93 operation.fractional_translation[dimension]));
102 Real two_pi_over_lattice_parameter_squared,
105 int& grid_dimension_1,
106 int& grid_dimension_2,
107 int& grid_dimension_3,
108 const int fft_factors[3] =
nullptr) {
109 Real g_vector_cutoff_squared = energy_cutoff / two_pi_over_lattice_parameter_squared;
110 Real square_root_g_vector_cutoff_squared = std::sqrt(g_vector_cutoff_squared);
112 int grid_estimate_1 =
static_cast<int>(std::floor(square_root_g_vector_cutoff_squared *
113 direct_lattice[0].norm())) +
115 int grid_estimate_2 =
static_cast<int>(std::floor(square_root_g_vector_cutoff_squared *
116 direct_lattice[1].norm())) +
118 int grid_estimate_3 =
static_cast<int>(std::floor(square_root_g_vector_cutoff_squared *
119 direct_lattice[2].norm())) +
122 int maximum_miller_index_1 = 0;
123 int maximum_miller_index_2 = 0;
124 int maximum_miller_index_3 = 0;
126 for (
int index_3 = -grid_estimate_3; index_3 <= grid_estimate_3; index_3++) {
127 for (
int index_2 = -grid_estimate_2; index_2 <= grid_estimate_2; index_2++) {
128 for (
int index_1 = -grid_estimate_1; index_1 <= grid_estimate_1; index_1++) {
130 for (
int dimension = 0; dimension < 3; dimension++) {
131 g_cartesian[dimension] = index_1 * reciprocal_lattice[0][dimension] +
132 index_2 * reciprocal_lattice[1][dimension] +
133 index_3 * reciprocal_lattice[2][dimension];
136 if (g_squared < g_vector_cutoff_squared +
138 maximum_miller_index_1 =
139 std::max(maximum_miller_index_1, std::abs(index_1));
140 maximum_miller_index_2 =
141 std::max(maximum_miller_index_2, std::abs(index_2));
142 maximum_miller_index_3 =
143 std::max(maximum_miller_index_3, std::abs(index_3));
149 grid_dimension_1 = 2 * maximum_miller_index_1 + 1;
150 grid_dimension_2 = 2 * maximum_miller_index_2 + 1;
151 grid_dimension_3 = 2 * maximum_miller_index_3 + 1;
153 int factor_1 = (fft_factors !=
nullptr) ? fft_factors[0] : 1;
154 int factor_2 = (fft_factors !=
nullptr) ? fft_factors[1] : 1;
155 int factor_3 = (fft_factors !=
nullptr) ? fft_factors[2] : 1;
174 int candidate_points = number_of_points;
176 if (division_factor > 1 && candidate_points % division_factor != 0) {
180 int remaining_factors = candidate_points;
181 while (remaining_factors % 2 == 0)
182 remaining_factors /= 2;
183 while (remaining_factors % 3 == 0)
184 remaining_factors /= 3;
185 while (remaining_factors % 5 == 0)
186 remaining_factors /= 5;
187 if (remaining_factors == 1)
188 return candidate_points;