diff --git a/src/main_gpumd/run.cu b/src/main_gpumd/run.cu
index dc714b6f9..b99101cb1 100644
--- a/src/main_gpumd/run.cu
+++ b/src/main_gpumd/run.cu
@@ -29,6 +29,7 @@ Run simulation according to the inputs in the run.in file.
#include "minimize/minimize.cuh"
#include "model/box.cuh"
#include "model/read_xyz.cuh"
+#include "model/check_distance.cuh"
#include "phonon/hessian.cuh"
#include "replicate.cuh"
#include "run.cuh"
@@ -115,6 +116,8 @@ Run::Run()
initialize_position(has_velocity_in_xyz, number_of_types, box, group, atom);
+ calculate_min_atomic_distance(atom, box);
+
allocate_memory_gpu(group, atom, thermo);
velocity.initialize(
diff --git a/src/model/check_distance.cu b/src/model/check_distance.cu
new file mode 100644
index 000000000..d473993de
--- /dev/null
+++ b/src/model/check_distance.cu
@@ -0,0 +1,169 @@
+/*
+ Copyright 2017 Zheyong Fan and GPUMD development team
+ This file is part of GPUMD.
+ GPUMD is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ GPUMD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GPUMD. If not, see .
+*/
+
+/*----------------------------------------------------------------------------80
+Calculate the distance between any two atoms in the model.xyz file.
+------------------------------------------------------------------------------*/
+
+#include "atom.cuh"
+#include "box.cuh"
+#include "check_distance.cuh"
+#include "utilities/error.cuh"
+#include
+
+void applyMicOne(double& x12)
+{
+ if (x12 < -0.5) {
+ x12 += 1.0;
+ } else if (x12 > +0.5) {
+ x12 -= 1.0;
+ }
+}
+
+void applyMic(const Box& box, double& x12, double& y12, double& z12)
+{
+ int pbc[3] = {box.pbc_x, box.pbc_y, box.pbc_z};
+ double s[3];
+ for (int i = 0; i < 3; ++i) {
+ s[i] = box.cpu_h[9 + i * 3] * x12 + box.cpu_h[10 + i * 3] * y12 + box.cpu_h[11 + i * 3] * z12;
+ if (pbc[i])
+ applyMicOne(s[i]);
+ }
+ x12 = box.cpu_h[0] * s[0] + box.cpu_h[3] * s[1] + box.cpu_h[6] * s[2];
+ y12 = box.cpu_h[1] * s[0] + box.cpu_h[4] * s[1] + box.cpu_h[7] * s[2];
+ z12 = box.cpu_h[2] * s[0] + box.cpu_h[5] * s[1] + box.cpu_h[8] * s[2];
+}
+
+void findCell(
+ const Box& box, const double* thickness, const double* r, const int* numCells, int* cell)
+{
+ double s[3];
+ for (int d = 0; d < 3; ++d) {
+ s[d] =
+ box.cpu_h[9 + d * 3] * r[0] + box.cpu_h[10 + d * 3] * r[1] + box.cpu_h[11 + d * 3] * r[2];
+ cell[d] = floor(s[d] * thickness[d] * 0.2);
+ if (cell[d] < 0)
+ cell[d] += numCells[d];
+ if (cell[d] >= numCells[d])
+ cell[d] -= numCells[d];
+ }
+ cell[3] = cell[0] + numCells[0] * (cell[1] + numCells[1] * cell[2]);
+}
+
+void calculate_min_atomic_distance(const Atom& atom, const Box& box)
+{
+ const int N = atom.number_of_atoms;
+ const double* pos = atom.cpu_position_per_atom.data();
+
+ double min_distance = 5.0;
+ int min_n1 = -1, min_n2 = -1;
+
+ int cell[4], numCells[4];
+ double thickness[3];
+ for (int i = 0; i < 3; ++i) {
+ thickness[i] = sqrt(
+ box.cpu_h[i] * box.cpu_h[i] + box.cpu_h[i + 3] * box.cpu_h[i + 3] +
+ box.cpu_h[i + 6] * box.cpu_h[i + 6]);
+ numCells[i] = std::max(1, static_cast(ceil(thickness[i] * 0.2)));
+ }
+ numCells[3] = numCells[0] * numCells[1] * numCells[2];
+
+ std::vector cellContents(N, 0);
+ std::vector cellCount(numCells[3], 0);
+ std::vector cellCountSum(numCells[3], 0);
+ std::fill(cellCount.begin(), cellCount.end(), 0);
+
+ for (int n = 0; n < N; ++n) {
+ const double r[3] = {pos[n], pos[n + N], pos[n + 2 * N]};
+ findCell(box, thickness, r, numCells, cell);
+ ++cellCount[cell[3]];
+ }
+
+ for (int i = 1; i < numCells[3]; ++i) {
+ cellCountSum[i] = cellCountSum[i - 1] + cellCount[i - 1];
+ }
+
+ for (int n = 0; n < N; ++n) {
+ const double r[3] = {pos[n], pos[n + N], pos[n + 2 * N]};
+ findCell(box, thickness, r, numCells, cell);
+ cellContents[cellCountSum[cell[3]] + cellCount[cell[3]]] = n;
+ ++cellCount[cell[3]];
+ }
+
+ for (int n1 = 0; n1 < N; ++n1) {
+ const double r1[3] = {pos[n1], pos[n1 + N], pos[n1 + 2 * N]};
+ findCell(box, thickness, r1, numCells, cell);
+ for (int k = -1; k <= 1; ++k) {
+ for (int j = -1; j <= 1; ++j) {
+ for (int i = -1; i <= 1; ++i) {
+ int neighborCell = cell[3] + (k * numCells[1] + j) * numCells[0] + i;
+ if (cell[0] + i < 0)
+ neighborCell += numCells[0];
+ if (cell[0] + i >= numCells[0])
+ neighborCell -= numCells[0];
+ if (cell[1] + j < 0)
+ neighborCell += numCells[1] * numCells[0];
+ if (cell[1] + j >= numCells[1])
+ neighborCell -= numCells[1] * numCells[0];
+ if (cell[2] + k < 0)
+ neighborCell += numCells[3];
+ if (cell[2] + k >= numCells[2])
+ neighborCell -= numCells[3];
+ for (int m = 0; m < cellCount[neighborCell]; ++m) {
+ const int n2 = cellContents[cellCountSum[neighborCell] + m];
+ if (n1 < n2) {
+ double x12 = pos[n2] - r1[0];
+ double y12 = pos[n2 + N] - r1[1];
+ double z12 = pos[n2 + 2 * N] - r1[2];
+ applyMic(box, x12, y12, z12);
+ if (fabs(x12) > 2.0 || fabs(y12) > 2.0 || fabs(z12) > 2.0)
+ continue;
+ const double d2 = x12 * x12 + y12 * y12 + z12 * z12;
+ if (d2 >= 4.0)
+ continue;
+
+ double distance = d2;
+ if (distance < min_distance) {
+ min_distance = distance;
+ min_n1 = n1;
+ min_n2 = n2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ double mini_distance = sqrt(min_distance);
+
+ if (mini_distance < 1.0) {
+ printf(
+ "Error: Minimum distance (%f Å) between atoms %d (%s) and %d (%s) is less than 1 Å.\n",
+ mini_distance,
+ min_n1,
+ atom.cpu_atom_symbol[min_n1].c_str(),
+ min_n2,
+ atom.cpu_atom_symbol[min_n2].c_str());
+ PRINT_INPUT_ERROR("There are two atoms with a distance less than 1 Å.");
+ } else if (min_n1 != -1 && min_n2 != -1) {
+ printf(
+ "Minimum distance between atoms %d (%s) and %d (%s): %f Å\n",
+ min_n1,
+ atom.cpu_atom_symbol[min_n1].c_str(),
+ min_n2,
+ atom.cpu_atom_symbol[min_n2].c_str(),
+ mini_distance);
+ }
+}
diff --git a/src/model/check_distance.cuh b/src/model/check_distance.cuh
new file mode 100644
index 000000000..903602b76
--- /dev/null
+++ b/src/model/check_distance.cuh
@@ -0,0 +1,21 @@
+/*
+ Copyright 2017 Zheyong Fan and GPUMD development team
+ This file is part of GPUMD.
+ GPUMD is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ GPUMD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GPUMD. If not, see .
+*/
+
+#pragma once
+
+class Box;
+class Atom;
+
+void calculate_min_atomic_distance(const Atom& atom, const Box& box);
\ No newline at end of file