|
1 | 1 | #include "source_cell/module_neighlist/neighbor_search.h" |
2 | 2 | #include <cmath> |
3 | 3 | #include <algorithm> |
| 4 | +#include <cstdint> |
4 | 5 | #include <limits> |
5 | 6 | #include <cassert> |
6 | 7 | #include <array> |
@@ -112,13 +113,14 @@ void NeighborSearch::init(const AtomProvider& ucell, double sr) |
112 | 113 | { |
113 | 114 | for (int j = 0; j < ucell.get_na(i); j++) |
114 | 115 | { |
| 116 | + const ModuleBase::Vector3<double> position = ucell.get_tau(i, j); |
115 | 117 | const ModuleNeighList::LocalAtomIndex atom_count |
116 | 118 | = ModuleNeighList::checked_local_atom_index(all_atoms_.size(), |
117 | 119 | "NeighborSearch atom id"); |
118 | 120 | NeighborAtom atom( |
119 | | - ucell.get_tau(i,j).x, |
120 | | - ucell.get_tau(i,j).y, |
121 | | - ucell.get_tau(i,j).z, |
| 121 | + position.x, |
| 122 | + position.y, |
| 123 | + position.z, |
122 | 124 | i, |
123 | 125 | j, |
124 | 126 | atom_count |
@@ -189,37 +191,111 @@ void NeighborSearch::check_expand_condition(const AtomProvider& ucell, int& glay |
189 | 191 |
|
190 | 192 | void NeighborSearch::set_member_variables(const AtomProvider& ucell, int glayerX_minus, int glayerX, int glayerY_minus, int glayerY, int glayerZ_minus, int glayerZ) |
191 | 193 | { |
192 | | - ModuleBase::Vector3<double> vec1(ucell.get_latvec().e11, ucell.get_latvec().e12, ucell.get_latvec().e13); |
193 | | - ModuleBase::Vector3<double> vec2(ucell.get_latvec().e21, ucell.get_latvec().e22, ucell.get_latvec().e23); |
194 | | - ModuleBase::Vector3<double> vec3(ucell.get_latvec().e31, ucell.get_latvec().e32, ucell.get_latvec().e33); |
| 194 | + if (glayerX_minus < 0 || glayerX < 0 || glayerY_minus < 0 || glayerY < 0 |
| 195 | + || glayerZ_minus < 0 || glayerZ < 0) |
| 196 | + { |
| 197 | + throw std::invalid_argument("NeighborSearch periodic image layers must be non-negative."); |
| 198 | + } |
195 | 199 |
|
196 | | - for (int ix = -glayerX_minus; ix < glayerX; ix++) |
| 200 | + const ModuleBase::Matrix3& lattice = ucell.get_latvec(); |
| 201 | + const ModuleBase::Vector3<double> vec1(lattice.e11, lattice.e12, lattice.e13); |
| 202 | + const ModuleBase::Vector3<double> vec2(lattice.e21, lattice.e22, lattice.e23); |
| 203 | + const ModuleBase::Vector3<double> vec3(lattice.e31, lattice.e32, lattice.e33); |
| 204 | + |
| 205 | + const std::size_t image_count_x |
| 206 | + = ModuleNeighList::checked_size_sum(static_cast<std::size_t>(glayerX_minus), |
| 207 | + static_cast<std::size_t>(glayerX), |
| 208 | + "NeighborSearch x image count"); |
| 209 | + const std::size_t image_count_y |
| 210 | + = ModuleNeighList::checked_size_sum(static_cast<std::size_t>(glayerY_minus), |
| 211 | + static_cast<std::size_t>(glayerY), |
| 212 | + "NeighborSearch y image count"); |
| 213 | + const std::size_t image_count_z |
| 214 | + = ModuleNeighList::checked_size_sum(static_cast<std::size_t>(glayerZ_minus), |
| 215 | + static_cast<std::size_t>(glayerZ), |
| 216 | + "NeighborSearch z image count"); |
| 217 | + const std::size_t image_count_yz |
| 218 | + = ModuleNeighList::checked_size_product(image_count_y, |
| 219 | + image_count_z, |
| 220 | + "NeighborSearch yz image count"); |
| 221 | + const std::size_t image_count |
| 222 | + = ModuleNeighList::checked_size_product(image_count_x, |
| 223 | + image_count_yz, |
| 224 | + "NeighborSearch periodic image count"); |
| 225 | + if (image_count == 0) |
197 | 226 | { |
198 | | - for (int iy = -glayerY_minus; iy < glayerY; iy++) |
199 | | - { |
200 | | - for (int iz = -glayerZ_minus; iz < glayerZ; iz++) |
201 | | - { |
202 | | - if(ix==0 && iy==0 && iz==0) |
203 | | - { |
204 | | - continue; |
205 | | - } |
206 | | - for (int i = 0; i < ucell.get_ntype(); i++) |
207 | | - { |
208 | | - for (int j = 0; j < ucell.get_na(i); j++) |
209 | | - { |
210 | | - double atom_x = ucell.get_tau(i,j).x + vec1[0] * ix + vec2[0] * iy + vec3[0] * iz; |
211 | | - double atom_y = ucell.get_tau(i,j).y + vec1[1] * ix + vec2[1] * iy + vec3[1] * iz; |
212 | | - double atom_z = ucell.get_tau(i,j).z + vec1[2] * ix + vec2[2] * iy + vec3[2] * iz; |
213 | | - |
214 | | - const ModuleNeighList::LocalAtomIndex atom_count |
215 | | - = ModuleNeighList::checked_local_atom_index(all_atoms_.size(), |
216 | | - "NeighborSearch atom id"); |
217 | | - NeighborAtom atom(atom_x, atom_y, atom_z, i, j, atom_count); |
218 | | - ghost_atoms_.push_back(atom); |
219 | | - all_atoms_.push_back(atom); |
220 | | - } |
221 | | - } |
222 | | - } |
223 | | - } |
| 227 | + throw std::invalid_argument("NeighborSearch periodic image range must contain the primary cell."); |
| 228 | + } |
| 229 | + |
| 230 | + const std::size_t origin_xy |
| 231 | + = ModuleNeighList::checked_size_sum( |
| 232 | + ModuleNeighList::checked_size_product(static_cast<std::size_t>(glayerX_minus), |
| 233 | + image_count_y, |
| 234 | + "NeighborSearch primary image index"), |
| 235 | + static_cast<std::size_t>(glayerY_minus), |
| 236 | + "NeighborSearch primary image index"); |
| 237 | + const std::size_t origin_image |
| 238 | + = ModuleNeighList::checked_size_sum( |
| 239 | + ModuleNeighList::checked_size_product(origin_xy, |
| 240 | + image_count_z, |
| 241 | + "NeighborSearch primary image index"), |
| 242 | + static_cast<std::size_t>(glayerZ_minus), |
| 243 | + "NeighborSearch primary image index"); |
| 244 | + |
| 245 | + const std::size_t base_atom_count = inside_atoms_.size(); |
| 246 | + const std::size_t ghost_image_count = image_count - 1; |
| 247 | + const std::size_t generated_atom_count |
| 248 | + = ModuleNeighList::checked_size_product(ghost_image_count, |
| 249 | + base_atom_count, |
| 250 | + "NeighborSearch generated atom count"); |
| 251 | + const std::size_t final_atom_count |
| 252 | + = ModuleNeighList::checked_size_sum(base_atom_count, |
| 253 | + generated_atom_count, |
| 254 | + "NeighborSearch total atom count"); |
| 255 | + if (final_atom_count > static_cast<std::size_t>(std::numeric_limits<ModuleNeighList::LocalAtomIndex>::max())) |
| 256 | + { |
| 257 | + throw std::overflow_error("NeighborSearch total atom count exceeds local atom index range."); |
| 258 | + } |
| 259 | + if (generated_atom_count == 0) |
| 260 | + { |
| 261 | + return; |
| 262 | + } |
| 263 | + |
| 264 | + const NeighborAtom placeholder(0.0, 0.0, 0.0, 0, 0, 0); |
| 265 | + all_atoms_.insert(all_atoms_.end(), generated_atom_count, placeholder); |
| 266 | + ghost_atoms_.assign(generated_atom_count, placeholder); |
| 267 | + |
| 268 | + // Thread creation costs more than it saves for small unit cells. |
| 269 | + const std::size_t parallel_threshold = 100000; |
| 270 | +#ifdef _OPENMP |
| 271 | +#pragma omp parallel for schedule(static) if(generated_atom_count >= parallel_threshold) |
| 272 | +#endif |
| 273 | + for (std::int64_t generated_index = 0; |
| 274 | + generated_index < static_cast<std::int64_t>(generated_atom_count); |
| 275 | + ++generated_index) |
| 276 | + { |
| 277 | + const std::size_t output_index = static_cast<std::size_t>(generated_index); |
| 278 | + const std::size_t ghost_image = output_index / base_atom_count; |
| 279 | + const std::size_t base_atom = output_index % base_atom_count; |
| 280 | + const std::size_t image = ghost_image < origin_image ? ghost_image : ghost_image + 1; |
| 281 | + const std::size_t image_x = image / image_count_yz; |
| 282 | + const std::size_t image_yz = image % image_count_yz; |
| 283 | + const std::size_t image_y = image_yz / image_count_z; |
| 284 | + const std::size_t image_z = image_yz % image_count_z; |
| 285 | + const double ix = static_cast<double>(image_x) - static_cast<double>(glayerX_minus); |
| 286 | + const double iy = static_cast<double>(image_y) - static_cast<double>(glayerY_minus); |
| 287 | + const double iz = static_cast<double>(image_z) - static_cast<double>(glayerZ_minus); |
| 288 | + |
| 289 | + const NeighborAtom& source = inside_atoms_[base_atom]; |
| 290 | + const ModuleNeighList::LocalAtomIndex atom_id |
| 291 | + = static_cast<ModuleNeighList::LocalAtomIndex>(base_atom_count + output_index); |
| 292 | + const NeighborAtom atom(source.position_x + vec1[0] * ix + vec2[0] * iy + vec3[0] * iz, |
| 293 | + source.position_y + vec1[1] * ix + vec2[1] * iy + vec3[1] * iz, |
| 294 | + source.position_z + vec1[2] * ix + vec2[2] * iy + vec3[2] * iz, |
| 295 | + source.atom_type, |
| 296 | + source.atom_index, |
| 297 | + atom_id); |
| 298 | + ghost_atoms_[output_index] = atom; |
| 299 | + all_atoms_[base_atom_count + output_index] = atom; |
224 | 300 | } |
225 | 301 | } |
0 commit comments