29void EAM::force(
long N,
const double *R,
const int *atomicNrs,
double *F,
30 double *U,
double *variance,
const double *fullbox) {
32 std::array<double, 3> box = {fullbox[0], fullbox[4], fullbox[8]};
34 std::array<long, 3> num_axis;
35 std::array<long, 3> cell_length;
37 for (
long i = 0; i < 3; i++) {
38 if (!(box[i] > 0.0) || !(
rc_[i] > 0.0)) {
39 throw std::invalid_argument(
40 "EAM::force: box diagonal and cutoff must be positive");
42 num_axis[i] =
static_cast<long>(box[i] /
rc_[i]) + 1;
44 for (
long i = 0; i < 3; i++) {
45 cell_length[i] =
static_cast<long>(box[i] / (num_axis[i] - 1));
48 long num_cells = num_axis[0] * num_axis[1] * num_axis[2];
57 for (
long k = 0; k < 3 * N; k++) {
62 double xmin = std::numeric_limits<double>::max();
63 double ymin = xmin, zmin = xmin;
65 std::vector<double> Rtemp(3 * N);
66 std::vector<double> Rnew(3 * N);
68 for (
long i = 0; i < 3 * N; i += 3) {
70 Rtemp[i + 1] = R[i + 1];
71 Rtemp[i + 2] = R[i + 2];
72 xmin = std::min(xmin, R[i]);
73 ymin = std::min(ymin, R[i + 1]);
74 zmin = std::min(zmin, R[i + 2]);
84 for (
long i = 0; i < 3 * N; i += 3) {
85 Rtemp[i] += std::abs(xmin);
86 Rtemp[i + 1] += std::abs(ymin);
87 Rtemp[i + 2] += std::abs(zmin);
91 for (
long i = 0; i < 3 * N; i++) {
92 while (Rtemp[i] > box[i % 3]) {
93 Rtemp[i] -= box[i % 3];
97 std::copy(Rtemp.begin(), Rtemp.end(), Rnew.begin());
100 new_celllist(N, box.data(), num_axis.data(), cell_length.data(),
107 new_celllist(N, box.data(), num_axis.data(), cell_length.data(),
114 calc_force(N, Rnew.data(), atomicNrs, F, U, box.data());
131 double *U,
const double *box) {
132 std::vector<double> drho_dr(3 * N);
133 for (
long k = 0; k < 3 * N; k++) {
139 const double halfBox0 = box[0] * 0.5;
140 const double halfBox1 = box[1] * 0.5;
141 const double halfBox2 = box[2] * 0.5;
143 for (
long i = 0; i < N; i++) {
144 std::fill(drho_dr.begin(), drho_dr.end(), 0.0);
146 const double cutoff2 = epar.
r_cut * epar.
r_cut;
149 const double xi = R[3 * i];
150 const double yi = R[3 * i + 1];
151 const double zi = R[3 * i + 2];
153 for (
long j = 0; j < N; j++) {
157 double dx = xi - R[3 * j];
158 double dy = yi - R[3 * j + 1];
159 double dz = zi - R[3 * j + 2];
164 else if (dx < -halfBox0)
168 else if (dy < -halfBox1)
172 else if (dz < -halfBox2)
175 double r2 = dx * dx + dy * dy + dz * dz;
180 double r = std::sqrt(r2);
183 double r6 = r2 * r2 * r2;
184 double exp_b1 = std::exp(-epar.
beta1 * r);
185 double exp_b2 = std::exp(-2.0 * epar.
beta2 * r);
186 double rho_pair = exp_b1 + 512.0 * exp_b2;
188 dens += r6 * rho_pair;
191 double r5 = r2 * r2 * r;
192 double mag_force_den =
193 6.0 * r5 * rho_pair +
194 r6 * (-epar.
beta1 * exp_b1 - 1024.0 * epar.
beta2 * exp_b2);
196 double invR = 1.0 / r;
197 double fscale = -mag_force_den * invR;
198 drho_dr[3 * i] += fscale * dx;
199 drho_dr[3 * i + 1] += fscale * dy;
200 drho_dr[3 * i + 2] += fscale * dz;
201 drho_dr[3 * j] -= fscale * dx;
202 drho_dr[3 * j + 1] -= fscale * dy;
203 drho_dr[3 * j + 2] -= fscale * dz;
207 double expArg = std::exp(-epar.
alphaM * (r - epar.
Rm));
208 double d = 1.0 - expArg;
209 double phi_r = epar.
Dm * d * d - epar.
Dm;
212 double mag_force = 2.0 * epar.
alphaM * epar.
Dm * d * (d - 1.0);
214 double fcomp_scale = mag_force * invR;
215 F[3 * i] -= fcomp_scale * dx;
216 F[3 * i + 1] -= fcomp_scale * dy;
217 F[3 * i + 2] -= fcomp_scale * dz;
218 F[3 * j] += fcomp_scale * dx;
219 F[3 * j + 1] += fcomp_scale * dy;
220 F[3 * j + 2] += fcomp_scale * dz;
227 for (
long k = 0; k < 3 * N; k++) {
228 F[k] -= dF_drho * drho_dr[k];
234 long *cell_length,
long *celllist_new,
long num_cells,
236 std::vector<long> cell_list(num_cells * (N + 1), -1);
238 for (
long i = 0; i < num_cells; i++) {
239 cell_list[i * (N + 1) + N] = 0;
242 for (
long i = 0; i < N; i++) {
243 long cx =
static_cast<long>(Rnew[3 * i] / cell_length[0]);
244 long cy =
static_cast<long>(Rnew[3 * i + 1] / cell_length[1]);
245 long cz =
static_cast<long>(Rnew[3 * i + 2] / cell_length[2]);
246 long cell = cx * num_axis[1] * num_axis[2] + cy * num_axis[2] + cz;
248 cell_list[cell * (N + 1) + cell_list[cell * (N + 1) + N]] = i;
249 cell_list[cell * (N + 1) + N]++;
252 std::copy(cell_list.begin(), cell_list.end(), celllist_new);
256 long * ,
long *celllist_new,
258 long num_cells = num_axis[0] * num_axis[1] * num_axis[2];
260 for (
long i = 0; i < N * (N + 1); i++) {
264 std::vector<long> neighbors(N + 1);
265 std::vector<long> cell_list_copy(num_cells * (N + 1));
267 for (
long j = 0; j < num_axis[0]; j++) {
268 for (
long j1 = 0; j1 < num_axis[1]; j1++) {
269 for (
long j2 = 0; j2 < num_axis[2]; j2++) {
270 std::fill(neighbors.begin(), neighbors.end(), -1);
272 long cur_index = j * num_axis[1] * num_axis[2] + j1 * num_axis[2] + j2;
274 std::copy(celllist_new, celllist_new + num_cells * (N + 1),
275 cell_list_copy.begin());
277 if (cell_list_copy[cur_index * (N + 1) + N] == 0) {
281 for (
long d1 = -1; d1 < 2; d1++) {
282 for (
long d2 = -1; d2 < 2; d2++) {
283 for (
long d3 = -1; d3 < 2; d3++) {
284 std::array<long, 3> pos = {j - d1, j1 - d2, j2 - d3};
286 for (
long y = 0; y < 3; y++) {
288 pos[y] = num_axis[y] - 1;
289 else if (pos[y] >= num_axis[y])
292 long neigh_index = pos[0] * num_axis[1] * num_axis[2] +
293 pos[1] * num_axis[2] + pos[2];
295 long num = cell_list_copy[neigh_index * (N + 1) + N];
296 for (
long y = 0; y < num; y++) {
297 long candidate = cell_list_copy[neigh_index * (N + 1) + y];
299 bool already =
false;
300 for (
long k = 0; k <= neighbors[N]; k++) {
301 if (neighbors[k] == candidate) {
308 neighbors[neighbors[N]] = candidate;
315 for (
long i = 0; i < celllist_new[cur_index * (N + 1) + N]; i++) {
316 long cur = celllist_new[cur_index * (N + 1) + i];
317 neigh_list[cur * (N + 1) + N] = 0;
318 for (
long temp = 0; temp <= neighbors[N]; temp++) {
319 if (cur != neighbors[temp]) {
320 neigh_list[cur * (N + 1) + neigh_list[cur * (N + 1) + N]] =
322 neigh_list[cur * (N + 1) + N]++;
332 long *cell_length,
long *celllist_old,
double *Rnew) {
334 std::vector<long> table(N);
336 for (
long i = 0; i < num_cells; i++) {
337 for (
long j = 0; j < celllist_old[i * (N + 1) + N]; j++) {
338 table[celllist_old[i * (N + 1) + j]] = i;
342 for (
long i = 0; i < N; i++) {
343 long cx =
static_cast<long>(Rnew[3 * i] / cell_length[0]);
344 long cy =
static_cast<long>(Rnew[3 * i + 1] / cell_length[1]);
345 long cz =
static_cast<long>(Rnew[3 * i + 2] / cell_length[2]);
346 long cell = cx * num_axis[1] * num_axis[2] + cy * num_axis[2] + cz;
347 if (cell != table[i]) {
void new_celllist(long N, const double *box, long *num_axis, long *cell_length, long *celllist_new, long num_cells, double *Rnew)
void force(long N, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *fullbox) override