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++)
278 double const * reference_origin,
279 double const * origin,
280 double const * reference_cell,
283 double const * reference_coordinates,
284 double const * coordinates,
285 const std::vector<std::string>& speciesCode,
286 int & numberOfPaddings,
287 std::vector<double> & reference_coordinatesOfPaddings,
288 std::vector<double> & coordinatesOfPaddings,
289 std::vector<std::string> & speciesCodeOfPaddings,
290 std::vector<int> & masterOfPaddings,
291 int referenceAndFinal)
298 int error =
inverse(tcell, fcell);
299 if (error) {
return error; }
303 double reference_tcell[9];
304 double reference_fcell[9];
305 if (referenceAndFinal)
307 transpose(reference_cell, reference_tcell);
309 int error =
inverse(reference_tcell, reference_fcell);
310 if (error) {
return error; }
314 double* frac_coords=
new double[
DIM * numberOfParticles];
315 double* reference_frac_coords=
nullptr;
316 if (referenceAndFinal) reference_frac_coords=
new double[
DIM * numberOfParticles];
317 double min[
DIM] = {1e10, 1e10, 1e10};
318 double max[
DIM] = {-1e10, -1e10, -1e10};
319 for (
int i = 0; i < numberOfParticles; i++)
321 const double * atom_coords = coordinates + (
DIM * i);
322 const double * reference_atom_coords = reference_coordinates + (
DIM * i);
323 double atom_coords_relative[
DIM];
324 for (
int j=0; j<
DIM; ++j) atom_coords_relative[j]= atom_coords[j] - origin[j];
325 double x =
dot(fcell, atom_coords_relative);
326 double y =
dot(fcell + 3, atom_coords_relative);
327 double z =
dot(fcell + 6, atom_coords_relative);
328 frac_coords[
DIM * i + 0] = x;
329 frac_coords[
DIM * i + 1] = y;
330 frac_coords[
DIM * i + 2] = z;
331 if (x < min[0]) { min[0] = x; }
332 if (y < min[1]) { min[1] = y; }
333 if (z < min[2]) { min[2] = z; }
334 if (x > max[0]) { max[0] = x; }
335 if (y > max[1]) { max[1] = y; }
336 if (z > max[2]) { max[2] = z; }
337 if(referenceAndFinal)
339 double reference_atom_coords_relative[
DIM];
340 for (
int j=0; j<
DIM; ++j) reference_atom_coords_relative[j]= reference_atom_coords[j] - reference_origin[j];
341 double reference_x =
dot(reference_fcell, reference_atom_coords_relative);
342 double reference_y =
dot(reference_fcell + 3, reference_atom_coords_relative);
343 double reference_z =
dot(reference_fcell + 6, reference_atom_coords_relative);
344 reference_frac_coords[
DIM * i + 0]= reference_x;
345 reference_frac_coords[
DIM * i + 1]= reference_y;
346 reference_frac_coords[
DIM * i + 2]= reference_z;
350 for (
int i = 0; i <
DIM; i++)
359 cross(cell + 3, cell + 6, xprod);
360 double volume = std::abs(
dot(cell, xprod));
364 cross(cell + 3, cell + 6, xprod);
365 dist[0] = volume /
norm(xprod);
366 cross(cell + 6, cell + 0, xprod);
367 dist[1] = volume /
norm(xprod);
368 cross(cell, cell + 3, xprod);
369 dist[2] = volume /
norm(xprod);
374 for (
int i = 0; i <
DIM; i++)
376 ratio[i] = cutoff / dist[i];
377 size[i] =
static_cast<int>(std::ceil(ratio[i]));
381 for (
int i = -size[0]; i <= size[0]; i++)
383 for (
int j = -size[1]; j <= size[1]; j++)
385 for (
int k = -size[2]; k <= size[2]; k++)
388 if (i == 0 && j == 0 && k == 0) {
continue; }
391 if (PBC[0] == 0 && i != 0) {
continue; }
392 if (PBC[1] == 0 && j != 0) {
continue; }
393 if (PBC[2] == 0 && k != 0) {
continue; }
395 for (
int at = 0; at < numberOfParticles; at++)
397 double x = frac_coords[
DIM * at + 0];
398 double y = frac_coords[
DIM * at + 1];
399 double z = frac_coords[
DIM * at + 2];
400 double reference_x, reference_y, reference_z;
401 if(referenceAndFinal)
403 reference_x= reference_frac_coords[
DIM * at + 0];
404 reference_y= reference_frac_coords[
DIM * at + 1];
405 reference_z= reference_frac_coords[
DIM * at + 2];
411 && x - min[0] <
static_cast<double>(size[0]) - ratio[0])
414 && max[0] - x <
static_cast<double>(size[0]) - ratio[0])
417 && y - min[1] <
static_cast<double>(size[1]) - ratio[1])
420 && max[1] - y <
static_cast<double>(size[1]) - ratio[1])
423 && z - min[2] <
static_cast<double>(size[2]) - ratio[2])
426 && max[2] - z <
static_cast<double>(size[2]) - ratio[2])
430 double atom_coords[3] = {i + x, j + y, k + z};
431 double reference_atom_coords[3];
432 if (referenceAndFinal)
434 reference_atom_coords[0]= i + reference_x;
435 reference_atom_coords[1]= j + reference_y;
436 reference_atom_coords[2]= k + reference_z;
440 coordinatesOfPaddings.push_back(origin[0] +
dot(tcell, atom_coords));
441 coordinatesOfPaddings.push_back(origin[1] +
dot(tcell + 3, atom_coords));
442 coordinatesOfPaddings.push_back(origin[2] +
dot(tcell + 6, atom_coords));
443 if (referenceAndFinal)
445 reference_coordinatesOfPaddings.push_back(reference_origin[0] +
dot(reference_tcell, reference_atom_coords));
446 reference_coordinatesOfPaddings.push_back(reference_origin[1] +
dot(reference_tcell + 3, reference_atom_coords));
447 reference_coordinatesOfPaddings.push_back(reference_origin[2] +
dot(reference_tcell + 6, reference_atom_coords));
451 speciesCodeOfPaddings.push_back(speciesCode[at]);
452 masterOfPaddings.push_back(at);
457 delete[] frac_coords;
458 if(reference_frac_coords!=
nullptr)
delete[] reference_frac_coords;
460 numberOfPaddings = masterOfPaddings.size();
int nbl_create_paddings(int const numberOfParticles, double const cutoff, double const *reference_origin, double const *origin, 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)