28void EAM::force(
long N,
const double *R,
const int *atomicNrs,
double *F,
29 double *U,
double *variance,
const double *fullbox) {
31 std::array<double, 3> box = {fullbox[0], fullbox[4], fullbox[8]};
33 std::array<long, 3> num_axis;
34 std::array<long, 3> cell_length;
36 for (
long i = 0; i < 3; i++) {
37 num_axis[i] =
static_cast<long>(box[i] /
rc_[i]) + 1;
39 for (
long i = 0; i < 3; i++) {
40 cell_length[i] =
static_cast<long>(box[i] / (num_axis[i] - 1));
43 long num_cells = num_axis[0] * num_axis[1] * num_axis[2];
52 for (
long k = 0; k < 3 * N; k++) {
57 double xmin = std::numeric_limits<double>::max();
58 double ymin = xmin, zmin = xmin;
60 std::vector<double> Rtemp(3 * N);
61 std::vector<double> Rnew(3 * N);
63 for (
long i = 0; i < 3 * N; i += 3) {
65 Rtemp[i + 1] = R[i + 1];
66 Rtemp[i + 2] = R[i + 2];
67 xmin = std::min(xmin, R[i]);
68 ymin = std::min(ymin, R[i + 1]);
69 zmin = std::min(zmin, R[i + 2]);
79 for (
long i = 0; i < 3 * N; i += 3) {
80 Rtemp[i] += std::abs(xmin);
81 Rtemp[i + 1] += std::abs(ymin);
82 Rtemp[i + 2] += std::abs(zmin);
86 for (
long i = 0; i < 3 * N; i++) {
87 while (Rtemp[i] > box[i % 3]) {
88 Rtemp[i] -= box[i % 3];
92 std::copy(Rtemp.begin(), Rtemp.end(), Rnew.begin());
95 new_celllist(N, box.data(), num_axis.data(), cell_length.data(),
102 new_celllist(N, box.data(), num_axis.data(), cell_length.data(),
109 calc_force(N, Rnew.data(), atomicNrs, F, U, box.data());
126 double *U,
const double *box) {
127 std::vector<double> drho_dr(3 * N);
128 for (
long k = 0; k < 3 * N; k++) {
134 const double halfBox0 = box[0] * 0.5;
135 const double halfBox1 = box[1] * 0.5;
136 const double halfBox2 = box[2] * 0.5;
138 for (
long i = 0; i < N; i++) {
139 std::fill(drho_dr.begin(), drho_dr.end(), 0.0);
141 const double cutoff2 = epar.
r_cut * epar.
r_cut;
144 const double xi = R[3 * i];
145 const double yi = R[3 * i + 1];
146 const double zi = R[3 * i + 2];
148 for (
long j = 0; j < N; j++) {
152 double dx = xi - R[3 * j];
153 double dy = yi - R[3 * j + 1];
154 double dz = zi - R[3 * j + 2];
159 else if (dx < -halfBox0)
163 else if (dy < -halfBox1)
167 else if (dz < -halfBox2)
170 double r2 = dx * dx + dy * dy + dz * dz;
175 double r = std::sqrt(r2);
178 double r6 = r2 * r2 * r2;
179 double exp_b1 = std::exp(-epar.
beta1 * r);
180 double exp_b2 = std::exp(-2.0 * epar.
beta2 * r);
181 double rho_pair = exp_b1 + 512.0 * exp_b2;
183 dens += r6 * rho_pair;
186 double r5 = r2 * r2 * r;
187 double mag_force_den =
188 6.0 * r5 * rho_pair +
189 r6 * (-epar.
beta1 * exp_b1 - 1024.0 * epar.
beta2 * exp_b2);
191 double invR = 1.0 / r;
192 double fscale = -mag_force_den * invR;
193 drho_dr[3 * i] += fscale * dx;
194 drho_dr[3 * i + 1] += fscale * dy;
195 drho_dr[3 * i + 2] += fscale * dz;
196 drho_dr[3 * j] -= fscale * dx;
197 drho_dr[3 * j + 1] -= fscale * dy;
198 drho_dr[3 * j + 2] -= fscale * dz;
202 double expArg = std::exp(-epar.
alphaM * (r - epar.
Rm));
203 double d = 1.0 - expArg;
204 double phi_r = epar.
Dm * d * d - epar.
Dm;
207 double mag_force = 2.0 * epar.
alphaM * epar.
Dm * d * (d - 1.0);
209 double fcomp_scale = mag_force * invR;
210 F[3 * i] -= fcomp_scale * dx;
211 F[3 * i + 1] -= fcomp_scale * dy;
212 F[3 * i + 2] -= fcomp_scale * dz;
213 F[3 * j] += fcomp_scale * dx;
214 F[3 * j + 1] += fcomp_scale * dy;
215 F[3 * j + 2] += fcomp_scale * dz;
222 for (
long k = 0; k < 3 * N; k++) {
223 F[k] -= dF_drho * drho_dr[k];
229 long *cell_length,
long *celllist_new,
long num_cells,
231 std::vector<long> cell_list(num_cells * (N + 1), -1);
233 for (
long i = 0; i < num_cells; i++) {
234 cell_list[i * (N + 1) + N] = 0;
237 for (
long i = 0; i < N; i++) {
238 long cx =
static_cast<long>(Rnew[3 * i] / cell_length[0]);
239 long cy =
static_cast<long>(Rnew[3 * i + 1] / cell_length[1]);
240 long cz =
static_cast<long>(Rnew[3 * i + 2] / cell_length[2]);
241 long cell = cx * num_axis[1] * num_axis[2] + cy * num_axis[2] + cz;
243 cell_list[cell * (N + 1) + cell_list[cell * (N + 1) + N]] = i;
244 cell_list[cell * (N + 1) + N]++;
247 std::copy(cell_list.begin(), cell_list.end(), celllist_new);
251 long * ,
long *celllist_new,
253 long num_cells = num_axis[0] * num_axis[1] * num_axis[2];
255 for (
long i = 0; i < N * (N + 1); i++) {
259 std::vector<long> neighbors(N + 1);
260 std::vector<long> cell_list_copy(num_cells * (N + 1));
262 for (
long j = 0; j < num_axis[0]; j++) {
263 for (
long j1 = 0; j1 < num_axis[1]; j1++) {
264 for (
long j2 = 0; j2 < num_axis[2]; j2++) {
265 std::fill(neighbors.begin(), neighbors.end(), -1);
267 long cur_index = j * num_axis[1] * num_axis[2] + j1 * num_axis[2] + j2;
269 std::copy(celllist_new, celllist_new + num_cells * (N + 1),
270 cell_list_copy.begin());
272 if (cell_list_copy[cur_index * (N + 1) + N] == 0) {
276 for (
long d1 = -1; d1 < 2; d1++) {
277 for (
long d2 = -1; d2 < 2; d2++) {
278 for (
long d3 = -1; d3 < 2; d3++) {
279 std::array<long, 3> pos = {j - d1, j1 - d2, j2 - d3};
281 for (
long y = 0; y < 3; y++) {
283 pos[y] = num_axis[y] - 1;
284 else if (pos[y] >= num_axis[y])
287 long neigh_index = pos[0] * num_axis[1] * num_axis[2] +
288 pos[1] * num_axis[2] + pos[2];
290 long num = cell_list_copy[neigh_index * (N + 1) + N];
291 for (
long y = 0; y < num; y++) {
292 long candidate = cell_list_copy[neigh_index * (N + 1) + y];
294 bool already =
false;
295 for (
long k = 0; k <= neighbors[N]; k++) {
296 if (neighbors[k] == candidate) {
303 neighbors[neighbors[N]] = candidate;
310 for (
long i = 0; i < celllist_new[cur_index * (N + 1) + N]; i++) {
311 long cur = celllist_new[cur_index * (N + 1) + i];
312 neigh_list[cur * (N + 1) + N] = 0;
313 for (
long temp = 0; temp <= neighbors[N]; temp++) {
314 if (cur != neighbors[temp]) {
315 neigh_list[cur * (N + 1) + neigh_list[cur * (N + 1) + N]] =
317 neigh_list[cur * (N + 1) + N]++;
327 long *cell_length,
long *celllist_old,
double *Rnew) {
329 std::vector<long> table(N);
331 for (
long i = 0; i < num_cells; i++) {
332 for (
long j = 0; j < celllist_old[i * (N + 1) + N]; j++) {
333 table[celllist_old[i * (N + 1) + j]] = i;
337 for (
long i = 0; i < N; i++) {
338 long cx =
static_cast<long>(Rnew[3 * i] / cell_length[0]);
339 long cy =
static_cast<long>(Rnew[3 * i + 1] / cell_length[1]);
340 long cz =
static_cast<long>(Rnew[3 * i + 2] / cell_length[2]);
341 long cell = cx * num_axis[1] * num_axis[2] + cy * num_axis[2] + cz;
342 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