45 int const numberOfCutoffs,
46 int const numberOfParticles)
50 for (
int i = 0; i < numberOfCutoffs; i++)
82 int const numberOfParticles,
83 double const * coordinates,
84 double const influenceDistance,
85 int const numberOfCutoffs,
86 double const * cutoffs,
87 int const * needNeighbors)
94 for (
int k = 0; k <
DIM; k++)
96 min[k] = coordinates[k];
97 max[k] = coordinates[k] + 1.0;
100 for (
int i = 0; i < numberOfParticles; i++)
102 for (
int j = 0; j <
DIM; j++)
104 if (max[j] < coordinates[DIM * i + j])
105 { max[j] = coordinates[DIM * i + j]; }
106 if (min[j] > coordinates[DIM * i + j])
107 { min[j] = coordinates[DIM * i + j]; }
114 for (
int i = 0; i <
DIM; i++)
116 size[i] =
static_cast<int>((max[i] - min[i]) / influenceDistance);
117 size[i] = size[i] <= 0 ? 1 : size[i];
118 size_total *= size[i];
120 if (size_total > 1000000000)
122 MY_WARNING(
"Cell size too large. Check if you have partilces fly away.");
127 std::vector<std::vector<int> > cells(size_total);
128 for (
int i = 0; i < numberOfParticles; i++)
132 int idx = index[0] + index[1] * size[0] + index[2] * size[0] * size[1];
133 cells[idx].push_back(i);
142 double * cutsqs =
new double[numberOfCutoffs];
143 for (
int i = 0; i < numberOfCutoffs; i++)
144 { cutsqs[i] = cutoffs[i] * cutoffs[i]; }
147 std::vector<int> * tmp_neigh =
new std::vector<int>[numberOfCutoffs];
148 int * total =
new int[numberOfCutoffs];
149 int * num_neigh =
new int[numberOfCutoffs];
150 for (
int k = 0; k < numberOfCutoffs; k++) { total[k] = 0; }
152 for (
int i = 0; i < numberOfParticles; i++)
154 for (
int k = 0; k < numberOfCutoffs; k++) { num_neigh[k] = 0; }
156 if (needNeighbors[i])
162 for (
int ii = std::max(0, index[0] - 1);
163 ii <= std::min(index[0] + 1, size[0] - 1);
166 for (
int jj = std::max(0, index[1] - 1);
167 jj <= std::min(index[1] + 1, size[1] - 1);
170 for (
int kk = std::max(0, index[2] - 1);
171 kk <= std::min(index[2] + 1, size[2] - 1);
174 int idx = ii + jj * size[0] + kk * size[0] * size[1];
176 for (
size_t m = 0; m < cells[idx].size(); m++)
178 int n = cells[idx][m];
183 for (
int k = 0; k <
DIM; k++)
186 = coordinates[DIM * n + k] - coordinates[DIM * i + k];
191 std::ostringstream stringStream;
192 stringStream <<
"Collision of atoms " << i + 1 <<
" and " 194 stringStream <<
"Their distance is " << std::sqrt(rsq) <<
"." 196 std::string my_str = stringStream.str();
200 for (
int k = 0; k < numberOfCutoffs; k++)
204 tmp_neigh[k].push_back(n);
215 for (
int k = 0; k < numberOfCutoffs; k++)
219 total[k] += num_neigh[k];
223 for (
int k = 0; k < numberOfCutoffs; k++)
242 int const numberOfCutoffs,
243 double const *
const cutoffs,
244 int const neighborListIndex,
245 int const particleNumber,
246 int *
const numberOfNeighbors,
247 int const **
const neighborsOfParticle)
255 if (cutoffs[neighborListIndex] > cnl->
cutoff +
TOL) {
return error; }
259 if ((particleNumber >= numberOfParticles) || (particleNumber < 0))
261 MY_WARNING(
"Invalid part ID in nbl_get_neigh");
266 *numberOfNeighbors = cnl->
Nneighbors[particleNumber];
278 double const * reference_cell,
281 double const * reference_coordinates,
282 double const * coordinates,
283 const std::vector<std::string>& speciesCode,
284 int & numberOfPaddings,
285 std::vector<double> & reference_coordinatesOfPaddings,
286 std::vector<double> & coordinatesOfPaddings,
287 std::vector<std::string> & speciesCodeOfPaddings,
288 std::vector<int> & masterOfPaddings,
289 int referenceAndFinal)
296 int error =
inverse(tcell, fcell);
297 if (error) {
return error; }
301 double reference_tcell[9];
302 double reference_fcell[9];
303 if (referenceAndFinal)
305 transpose(reference_cell, reference_tcell);
307 int error =
inverse(reference_tcell, reference_fcell);
308 if (error) {
return error; }
312 double* frac_coords=
new double[
DIM * numberOfParticles];
313 double* reference_frac_coords=
nullptr;
314 if (referenceAndFinal) reference_frac_coords=
new double[
DIM * numberOfParticles];
315 double min[
DIM] = {1e10, 1e10, 1e10};
316 double max[
DIM] = {-1e10, -1e10, -1e10};
317 for (
int i = 0; i < numberOfParticles; i++)
319 const double * atom_coords = coordinates + (
DIM * i);
320 const double * reference_atom_coords = reference_coordinates + (
DIM * i);
321 double x =
dot(fcell, atom_coords);
322 double y =
dot(fcell + 3, atom_coords);
323 double z =
dot(fcell + 6, atom_coords);
324 frac_coords[
DIM * i + 0] = x;
325 frac_coords[
DIM * i + 1] = y;
326 frac_coords[
DIM * i + 2] = z;
327 if (x < min[0]) { min[0] = x; }
328 if (y < min[1]) { min[1] = y; }
329 if (z < min[2]) { min[2] = z; }
330 if (x > max[0]) { max[0] = x; }
331 if (y > max[1]) { max[1] = y; }
332 if (z > max[2]) { max[2] = z; }
333 if(referenceAndFinal)
335 double reference_x =
dot(reference_fcell, reference_atom_coords);
336 double reference_y =
dot(reference_fcell + 3, reference_atom_coords);
337 double reference_z =
dot(reference_fcell + 6, reference_atom_coords);
338 reference_frac_coords[
DIM * i + 0]= reference_x;
339 reference_frac_coords[
DIM * i + 1]= reference_y;
340 reference_frac_coords[
DIM * i + 2]= reference_z;
344 for (
int i = 0; i <
DIM; i++)
352 cross(cell + 3, cell + 6, xprod);
353 double volume = std::abs(
dot(cell, xprod));
357 cross(cell + 3, cell + 6, xprod);
358 dist[0] = volume /
norm(xprod);
359 cross(cell + 6, cell + 0, xprod);
360 dist[1] = volume /
norm(xprod);
361 cross(cell, cell + 3, xprod);
362 dist[2] = volume /
norm(xprod);
367 for (
int i = 0; i <
DIM; i++)
369 ratio[i] = cutoff / dist[i];
370 size[i] =
static_cast<int>(std::ceil(ratio[i]));
374 for (
int i = -size[0]; i <= size[0]; i++)
376 for (
int j = -size[1]; j <= size[1]; j++)
378 for (
int k = -size[2]; k <= size[2]; k++)
381 if (i == 0 && j == 0 && k == 0) {
continue; }
384 if (PBC[0] == 0 && i != 0) {
continue; }
385 if (PBC[1] == 0 && j != 0) {
continue; }
386 if (PBC[2] == 0 && k != 0) {
continue; }
388 for (
int at = 0; at < numberOfParticles; at++)
390 double x = frac_coords[DIM * at + 0];
391 double y = frac_coords[DIM * at + 1];
392 double z = frac_coords[DIM * at + 2];
393 double reference_x, reference_y, reference_z;
394 if(referenceAndFinal)
396 reference_x= reference_frac_coords[DIM * at + 0];
397 reference_y= reference_frac_coords[DIM * at + 1];
398 reference_z= reference_frac_coords[DIM * at + 2];
404 && x - min[0] < static_cast<double>(size[0]) - ratio[0])
407 && max[0] - x < static_cast<double>(size[0]) - ratio[0])
410 && y - min[1] < static_cast<double>(size[1]) - ratio[1])
413 && max[1] - y < static_cast<double>(size[1]) - ratio[1])
416 && z - min[2] < static_cast<double>(size[2]) - ratio[2])
419 && max[2] - z < static_cast<double>(size[2]) - ratio[2])
423 double atom_coords[3] = {i + x, j + y, k + z};
424 double reference_atom_coords[3];
425 if (referenceAndFinal)
427 reference_atom_coords[0]= i + reference_x;
428 reference_atom_coords[1]= j + reference_y;
429 reference_atom_coords[2]= k + reference_z;
433 coordinatesOfPaddings.push_back(
dot(tcell, atom_coords));
434 coordinatesOfPaddings.push_back(
dot(tcell + 3, atom_coords));
435 coordinatesOfPaddings.push_back(
dot(tcell + 6, atom_coords));
436 if (referenceAndFinal)
438 reference_coordinatesOfPaddings.push_back(
dot(reference_tcell, reference_atom_coords));
439 reference_coordinatesOfPaddings.push_back(
dot(reference_tcell + 3, reference_atom_coords));
440 reference_coordinatesOfPaddings.push_back(
dot(reference_tcell + 6, reference_atom_coords));
444 speciesCodeOfPaddings.push_back(speciesCode[at]);
445 masterOfPaddings.push_back(at);
450 delete[] frac_coords;
451 if(reference_frac_coords!=
nullptr)
delete[] reference_frac_coords;
453 numberOfPaddings = masterOfPaddings.size();
void transpose(double const *mat, double *const trans)
int numberOfNeighborLists
void nbl_initialize(NeighList **const nl)
double dot(double const *a, double const *b)
#define MY_WARNING(message)
void nbl_clean(NeighList **const nl)
void cross(double const *a, double const *b, double *const axb)
int inverse(double const *mat, double *const inv)
double norm(double const *a)
void nbl_clean_content(NeighList *const nl)
int nbl_get_neigh(void const *const dataObject, int const numberOfCutoffs, double const *const cutoffs, int const neighborListIndex, int const particleNumber, int *const numberOfNeighbors, int const **const neighborsOfParticle)
void nbl_allocate_memory(NeighList *const nl, int const numberOfCutoffs, int const numberOfParticles)
int nbl_create_paddings(int const numberOfParticles, double const cutoff, double const *reference_cell, double const *cell, int const *PBC, double const *reference_coordinates, double const *coordinates, const std::vector< std::string > &speciesCode, int &numberOfPaddings, std::vector< double > &reference_coordinatesOfPaddings, std::vector< double > &coordinatesOfPaddings, std::vector< std::string > &speciesCodeOfPaddings, std::vector< int > &masterOfPaddings, int referenceAndFinal)
int nbl_build(NeighList *const nl, int const numberOfParticles, double const *coordinates, double const influenceDistance, int const numberOfCutoffs, double const *cutoffs, int const *needNeighbors)
void coords_to_index(double const *x, int const *size, double const *max, double const *min, int *const index)