22#include < cmath>
33#include < algorithm>
44#include < cassert>
5+ #include < stdexcept>
56#include " bin_manager.h"
67
78// ========== Bin class implementation ==========
89
9- int Bin::get_id_x () const {
10- return id_x_;
11- }
12-
13- int Bin::get_id_y () const {
14- return id_y_;
15- }
16-
17- int Bin::get_id_z () const {
18- return id_z_;
19- }
20-
21- const std::vector<NeighborAtom>& Bin::get_atoms () const {
22- return atoms_;
10+ const std::vector<ModuleNeighList::LocalAtomIndex>& Bin::get_atom_indices () const {
11+ return atom_indices_;
2312}
2413
2514void Bin::set_id (int ix, int iy, int iz) {
@@ -29,11 +18,11 @@ void Bin::set_id(int ix, int iy, int iz) {
2918}
3019
3120void Bin::clear_atoms () {
32- atoms_ .clear ();
21+ atom_indices_ .clear ();
3322}
3423
35- void Bin::add_atom ( const NeighborAtom& atom ) {
36- atoms_ .push_back (atom );
24+ void Bin::add_atom_index (ModuleNeighList::LocalAtomIndex atom_index ) {
25+ atom_indices_ .push_back (atom_index );
3726}
3827
3928// ========== BinManager getter methods ==========
@@ -51,26 +40,30 @@ int BinManager::get_nbinz() const {
5140}
5241
5342int BinManager::get_total_bins () const {
54- return static_cast < int > (bins_.size ());
43+ return ModuleNeighList::checked_int_size (bins_.size (), " BinManager total bin count " );
5544}
5645
5746int BinManager::get_bin_atom_count (int bin_index) const {
58- if (bin_index < 0 || bin_index >= static_cast < int >( bins_.size () )) {
47+ if (bin_index < 0 || static_cast <std:: size_t >( bin_index) >= bins_.size ()) {
5948 return 0 ;
6049 }
61- return static_cast <int >(bins_[bin_index].get_atoms ().size ());
50+ return ModuleNeighList::checked_int_size (bins_[bin_index].get_atom_indices ().size (),
51+ " Bin atom count" );
6252}
6353
6454// ========== BinManager main methods ==========
6555
6656void BinManager::init_bins (
6757 double sr,
68- const std::vector<NeighborAtom>& inside_atoms,
69- const std::vector<NeighborAtom>& ghost_atoms
58+ const std::vector<NeighborAtom>& all_atoms
7059)
7160{
7261 sradius_ = sr;
73- if (inside_atoms.empty () && ghost_atoms.empty ())
62+ if (!std::isfinite (sradius_) || sradius_ <= 0.0 )
63+ {
64+ throw std::invalid_argument (" BinManager search radius must be finite and positive." );
65+ }
66+ if (all_atoms.empty ())
7467 {
7568 x_min_ = y_min_ = z_min_ = 0 ;
7669 x_max_ = y_max_ = z_max_ = 0 ;
@@ -98,20 +91,34 @@ void BinManager::init_bins(
9891 }
9992 };
10093
101- update_bounds (inside_atoms);
102- update_bounds (ghost_atoms);
94+ update_bounds (all_atoms);
10395
10496 bin_sizex_ = bin_sizey_ = bin_sizez_ = sradius_;
10597
106- nbinx_ = std::ceil ((x_max_ - x_min_) / bin_sizex_);
107- nbiny_ = std::ceil ((y_max_ - y_min_) / bin_sizey_);
108- nbinz_ = std::ceil ((z_max_ - z_min_) / bin_sizez_);
98+ const auto checked_bin_dimension = [](const double span, const double bin_size, const char * context) {
99+ const double count = std::ceil (span / bin_size);
100+ if (!std::isfinite (count) || count > static_cast <double >(std::numeric_limits<int >::max ()))
101+ {
102+ throw std::overflow_error (std::string (context) + " exceeds int range." );
103+ }
104+ return static_cast <int >(count);
105+ };
106+
107+ nbinx_ = checked_bin_dimension (x_max_ - x_min_, bin_sizex_, " BinManager X bin count" );
108+ nbiny_ = checked_bin_dimension (y_max_ - y_min_, bin_sizey_, " BinManager Y bin count" );
109+ nbinz_ = checked_bin_dimension (z_max_ - z_min_, bin_sizez_, " BinManager Z bin count" );
109110
110111 nbinx_ = std::max (1 , nbinx_);
111112 nbiny_ = std::max (1 , nbiny_);
112113 nbinz_ = std::max (1 , nbinz_);
113114
114- int nbins = nbinx_ * nbiny_ * nbinz_;
115+ const std::size_t nbins_xy = ModuleNeighList::checked_size_product (static_cast <std::size_t >(nbinx_),
116+ static_cast <std::size_t >(nbiny_),
117+ " BinManager bin count" );
118+ const std::size_t nbins_size = ModuleNeighList::checked_size_product (nbins_xy,
119+ static_cast <std::size_t >(nbinz_),
120+ " BinManager bin count" );
121+ const int nbins = ModuleNeighList::checked_int_size (nbins_size, " BinManager bin count" );
115122
116123 bins_.clear ();
117124 bins_.resize (nbins);
@@ -132,12 +139,17 @@ void BinManager::init_bins(
132139}
133140
134141void BinManager::do_binning (
135- const std::vector<NeighborAtom>& inside_atoms,
136- const std::vector<NeighborAtom>& ghost_atoms
142+ const std::vector<NeighborAtom>& atoms
137143)
138144{
139- auto bin_atom = [&]( const NeighborAtom& atom )
145+ if (atoms. size () > static_cast <std:: size_t >(std::numeric_limits<ModuleNeighList::LocalAtomIndex>:: max ()) )
140146 {
147+ throw std::overflow_error (" BinManager binned atom count exceeds local atom index range." );
148+ }
149+
150+ for (std::size_t iatom = 0 ; iatom < atoms.size (); ++iatom)
151+ {
152+ const NeighborAtom& atom = atoms[iatom];
141153 int ix = std::min (
142154 std::max (int ((atom.position_x - x_min_) / bin_sizex_), 0 ),
143155 nbinx_ - 1
@@ -155,11 +167,9 @@ void BinManager::do_binning(
155167
156168 int idx = bin_index (ix, iy, iz);
157169
158- bins_[idx].add_atom (atom);
159- };
160-
161- for (const auto & atom : inside_atoms) bin_atom (atom);
162- for (const auto & atom : ghost_atoms) bin_atom (atom);
170+ const ModuleNeighList::LocalAtomIndex atom_index = static_cast <ModuleNeighList::LocalAtomIndex>(iatom);
171+ bins_[idx].add_atom_index (atom_index);
172+ }
163173}
164174
165175int BinManager::bin_index (int ix, int iy, int iz) const {
@@ -168,7 +178,8 @@ int BinManager::bin_index(int ix, int iy, int iz) const {
168178
169179void BinManager::build_atom_neighbors (
170180 NeighborList& neighbor_list,
171- std::vector<NeighborAtom>& atoms
181+ const std::vector<NeighborAtom>& atoms,
182+ const std::vector<NeighborAtom>& binned_atoms
172183)
173184{
174185 assert (atoms.size () == static_cast <size_t >(neighbor_list.get_nlocal ()));
@@ -179,22 +190,24 @@ void BinManager::build_atom_neighbors(
179190
180191 std::vector<int > neigh_tmp;
181192
182- for (int i = 0 ; i < atoms.size (); i++)
193+ const int nlocal = neighbor_list.get_nlocal ();
194+ for (int i = 0 ; i < nlocal; i++)
183195 {
184196 neigh_tmp.clear ();
197+ const NeighborAtom& atom = atoms[i];
185198
186199 int ix = std::min (
187- std::max (int ((atoms[i] .position_x - x_min_) / bin_sizex_), 0 ),
200+ std::max (int ((atom .position_x - x_min_) / bin_sizex_), 0 ),
188201 nbinx_ - 1
189202 );
190203
191204 int iy = std::min (
192- std::max (int ((atoms[i] .position_y - y_min_) / bin_sizey_), 0 ),
205+ std::max (int ((atom .position_y - y_min_) / bin_sizey_), 0 ),
193206 nbiny_ - 1
194207 );
195208
196209 int iz = std::min (
197- std::max (int ((atoms[i] .position_z - z_min_) / bin_sizez_), 0 ),
210+ std::max (int ((atom .position_z - z_min_) / bin_sizez_), 0 ),
198211 nbinz_ - 1
199212 );
200213
@@ -215,15 +228,20 @@ void BinManager::build_atom_neighbors(
215228
216229 int nidx = bin_index (jx, jy, jz);
217230
218- for (const NeighborAtom& natom : bins_[nidx].get_atoms ())
231+ for (const ModuleNeighList::LocalAtomIndex binned_atom_index : bins_[nidx].get_atom_indices ())
219232 {
220- double dx = atoms[i].position_x - natom.position_x ;
221- double dy = atoms[i].position_y - natom.position_y ;
222- double dz = atoms[i].position_z - natom.position_z ;
233+ const NeighborAtom& natom = binned_atoms[static_cast <std::size_t >(binned_atom_index)];
234+ double dx = atom.position_x - natom.position_x ;
235+ double dy = atom.position_y - natom.position_y ;
236+ double dz = atom.position_z - natom.position_z ;
223237
224238 double dist2 = dx * dx + dy * dy + dz * dz;
225239
226- if (dist2 <= sradius2 && dist2 != 0 )
240+ if (natom.atom_id == atom.atom_id )
241+ {
242+ continue ;
243+ }
244+ if (dist2 <= sradius2)
227245 {
228246 neigh_tmp.push_back (natom.atom_id );
229247 }
@@ -232,7 +250,7 @@ void BinManager::build_atom_neighbors(
232250 }
233251 }
234252
235- int n = neigh_tmp.size ();
253+ const int n = ModuleNeighList::checked_int_size ( neigh_tmp.size (), " BinManager neighbor count " );
236254
237255 int * ptr = neighbor_list.allocator_ .allocate (n);
238256
@@ -255,4 +273,4 @@ void BinManager::clear()
255273 }
256274
257275 bins_.clear ();
258- }
276+ }
0 commit comments