// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories LAMMPS development team: developers@lammps.org Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "meam.h" #include "math_special.h" #include #include using namespace LAMMPS_NS; void MEAM::meam_force(int i, int eflag_global, int eflag_atom, int vflag_global, int vflag_atom, double *eng_vdwl, double *eatom, int /*ntype*/, int *type, int *fmap, double **scale, double **x, int numneigh, int *firstneigh, int numneigh_full, int *firstneigh_full, int fnoffset, double **f, double **vatom, double *virial) { int j, jn, k, kn, kk, m, n, p, q; int nv2, nv3, elti, eltj, eltk, ind; int eflag_either = eflag_atom || eflag_global; int vflag_either = vflag_atom || vflag_global; double xitmp, yitmp, zitmp, delij[3], rij2, rij, rij3; double v[6], fi[3], fj[3]; double third, sixth; double pp, dUdrij, dUdsij, dUdrijm[3], force, forcem; double recip, phi, phip; double sij; double a1, a1i, a1j, a2, a2i, a2j; double a3i, a3j; double shpi[3], shpj[3]; double ai, aj, ro0i, ro0j, invrei, invrej; double rhoa0j, drhoa0j, rhoa0i, drhoa0i; double rhoa1j, drhoa1j, rhoa1i, drhoa1i; double rhoa2j, drhoa2j, rhoa2i, drhoa2i; double a3, a3a, rhoa3j, drhoa3j, rhoa3i, drhoa3i; double drho0dr1, drho0dr2, drho0ds1, drho0ds2; double drho1dr1, drho1dr2, drho1ds1, drho1ds2; double drho1drm1[3], drho1drm2[3]; double drho2dr1, drho2dr2, drho2ds1, drho2ds2; double drho2drm1[3], drho2drm2[3]; double drho3dr1, drho3dr2, drho3ds1, drho3ds2; double drho3drm1[3], drho3drm2[3]; double dt1dr1, dt1dr2, dt1ds1, dt1ds2; double dt2dr1, dt2dr2, dt2ds1, dt2ds2; double dt3dr1, dt3dr2, dt3ds1, dt3ds2; double drhodr1, drhodr2, drhods1, drhods2, drhodrm1[3], drhodrm2[3]; double arg; double arg1i1, arg1j1, arg1i2, arg1j2, arg1i3, arg1j3, arg3i3, arg3j3; double dsij1, dsij2, force1, force2; double t1i, t2i, t3i, t1j, t2j, t3j; double scaleij; double rhoa1mj,drhoa1mj,rhoa1mi,drhoa1mi; double rhoa2mj,drhoa2mj,rhoa2mi,drhoa2mi; double rhoa3mj, drhoa3mj, rhoa3mi, drhoa3mi; double arg1i1m, arg1j1m, arg1i2m, arg1j2m, arg1i3m, arg1j3m, arg3i3m, arg3j3m; double drho1mdr1, drho1mdr2; double drho1mdrm1[3], drho1mdrm2[3]; double drho2mdr1, drho2mdr2; double drho2mdrm1[3], drho2mdrm2[3]; double drho3mdr1, drho3mdr2; double drho3mdrm1[3], drho3mdrm2[3]; third = 1.0 / 3.0; sixth = 1.0 / 6.0; // Compute forces atom i elti = fmap[type[i]]; if (elti < 0) return; xitmp = x[i][0]; yitmp = x[i][1]; zitmp = x[i][2]; // Treat each pair for (jn = 0; jn < numneigh; jn++) { j = firstneigh[jn]; eltj = fmap[type[j]]; scaleij = scale[type[i]][type[j]]; if (!iszero(scrfcn[fnoffset + jn]) && eltj >= 0) { sij = scrfcn[fnoffset + jn] * fcpair[fnoffset + jn]; delij[0] = x[j][0] - xitmp; delij[1] = x[j][1] - yitmp; delij[2] = x[j][2] - zitmp; rij2 = delij[0] * delij[0] + delij[1] * delij[1] + delij[2] * delij[2]; if (rij2 < cutforcesq) { rij = sqrt(rij2); recip = 1.0 / rij; // Compute phi and phip ind = eltind[elti][eltj]; pp = rij * rdrar; kk = (int)pp; kk = std::min(kk, nrar - 2); pp = pp - kk; pp = std::min(pp, 1.0); phi = ((phirar3[ind][kk] * pp + phirar2[ind][kk]) * pp + phirar1[ind][kk]) * pp + phirar[ind][kk]; phip = (phirar6[ind][kk] * pp + phirar5[ind][kk]) * pp + phirar4[ind][kk]; if (eflag_either != 0) { double phi_sc = phi * scaleij; if (eflag_global != 0) *eng_vdwl = *eng_vdwl + phi_sc * sij; if (eflag_atom != 0) { eatom[i] = eatom[i] + 0.5 * phi_sc * sij; eatom[j] = eatom[j] + 0.5 * phi_sc * sij; } } // write(1,*) "force_meamf: phi: ",phi // write(1,*) "force_meamf: phip: ",phip // Compute pair densities and derivatives invrei = 1.0 / re_meam[elti][elti]; ai = rij * invrei - 1.0; ro0i = rho0_meam[elti]; rhoa0i = ro0i * MathSpecial::fm_exp(-beta0_meam[elti] * ai); drhoa0i = -beta0_meam[elti] * invrei * rhoa0i; rhoa1i = ro0i * MathSpecial::fm_exp(-beta1_meam[elti] * ai); drhoa1i = -beta1_meam[elti] * invrei * rhoa1i; rhoa2i = ro0i * MathSpecial::fm_exp(-beta2_meam[elti] * ai); drhoa2i = -beta2_meam[elti] * invrei * rhoa2i; rhoa3i = ro0i * MathSpecial::fm_exp(-beta3_meam[elti] * ai); drhoa3i = -beta3_meam[elti] * invrei * rhoa3i; if (msmeamflag) { rhoa1mi = ro0i * MathSpecial::fm_exp(-beta1m_meam[elti] * ai) * t1m_meam[elti]; drhoa1mi = -beta1m_meam[elti] * invrei * rhoa1mi; rhoa2mi = ro0i * MathSpecial::fm_exp(-beta2m_meam[elti] * ai) * t2m_meam[elti]; drhoa2mi = -beta2m_meam[elti] * invrei * rhoa2mi; rhoa3mi = ro0i * MathSpecial::fm_exp(-beta3m_meam[elti] * ai) * t3m_meam[elti]; drhoa3mi = -beta3m_meam[elti] * invrei * rhoa3mi; } if (elti != eltj) { invrej = 1.0 / re_meam[eltj][eltj]; aj = rij * invrej - 1.0; ro0j = rho0_meam[eltj]; rhoa0j = ro0j * MathSpecial::fm_exp(-beta0_meam[eltj] * aj); drhoa0j = -beta0_meam[eltj] * invrej * rhoa0j; rhoa1j = ro0j * MathSpecial::fm_exp(-beta1_meam[eltj] * aj); drhoa1j = -beta1_meam[eltj] * invrej * rhoa1j; rhoa2j = ro0j * MathSpecial::fm_exp(-beta2_meam[eltj] * aj); drhoa2j = -beta2_meam[eltj] * invrej * rhoa2j; rhoa3j = ro0j * MathSpecial::fm_exp(-beta3_meam[eltj] * aj); drhoa3j = -beta3_meam[eltj] * invrej * rhoa3j; if (msmeamflag) { rhoa1mj = ro0j * t1m_meam[eltj] * MathSpecial::fm_exp(-beta1m_meam[eltj] * aj); drhoa1mj = -beta1m_meam[eltj] * invrej * rhoa1mj; rhoa2mj = ro0j * t2m_meam[eltj] * MathSpecial::fm_exp(-beta2m_meam[eltj] * aj); drhoa2mj = -beta2m_meam[eltj] * invrej * rhoa2mj; rhoa3mj = ro0j * t3m_meam[eltj] * MathSpecial::fm_exp(-beta3m_meam[eltj] * aj); drhoa3mj = -beta3m_meam[eltj] * invrej * rhoa3mj; } } else { rhoa0j = rhoa0i; drhoa0j = drhoa0i; rhoa1j = rhoa1i; drhoa1j = drhoa1i; rhoa2j = rhoa2i; drhoa2j = drhoa2i; rhoa3j = rhoa3i; drhoa3j = drhoa3i; if (msmeamflag) { rhoa1mj = rhoa1mi; drhoa1mj = drhoa1mi; rhoa2mj = rhoa2mi; drhoa2mj = drhoa2mi; rhoa3mj = rhoa3mi; drhoa3mj = drhoa3mi; } } const double t1mi = t1_meam[elti]; const double t2mi = t2_meam[elti]; const double t3mi = t3_meam[elti]; const double t1mj = t1_meam[eltj]; const double t2mj = t2_meam[eltj]; const double t3mj = t3_meam[eltj]; // ialloy mod not needed in MS-MEAM, but similarity here is that we multply rhos by t. // We did this above with rhoa1mj, rhoa2mj, etc. if (ialloy == 1 || msmeamflag) { rhoa1j *= t1mj; rhoa2j *= t2mj; rhoa3j *= t3mj; rhoa1i *= t1mi; rhoa2i *= t2mi; rhoa3i *= t3mi; drhoa1j *= t1mj; drhoa2j *= t2mj; drhoa3j *= t3mj; drhoa1i *= t1mi; drhoa2i *= t2mi; drhoa3i *= t3mi; } nv2 = 0; nv3 = 0; arg1i1 = 0.0; arg1j1 = 0.0; arg1i2 = 0.0; arg1j2 = 0.0; arg1i3 = 0.0; arg1j3 = 0.0; arg3i3 = 0.0; arg3j3 = 0.0; for (n = 0; n < 3; n++) { for (p = n; p < 3; p++) { for (q = p; q < 3; q++) { arg = delij[n] * delij[p] * delij[q] * v3D[nv3]; arg1i3 = arg1i3 + arho3[i][nv3] * arg; arg1j3 = arg1j3 - arho3[j][nv3] * arg; nv3 = nv3 + 1; } arg = delij[n] * delij[p] * v2D[nv2]; arg1i2 = arg1i2 + arho2[i][nv2] * arg; arg1j2 = arg1j2 + arho2[j][nv2] * arg; nv2 = nv2 + 1; } arg1i1 = arg1i1 + arho1[i][n] * delij[n]; arg1j1 = arg1j1 - arho1[j][n] * delij[n]; arg3i3 = arg3i3 + arho3b[i][n] * delij[n]; arg3j3 = arg3j3 - arho3b[j][n] * delij[n]; } // msmeam arhom args nv2 = 0; nv3 = 0; arg1i1m = 0.0; arg1j1m = 0.0; arg1i2m = 0.0; arg1j2m = 0.0; arg1i3m = 0.0; arg1j3m = 0.0; arg3i3m = 0.0; arg3j3m = 0.0; if (msmeamflag) { for (n = 0; n < 3; n++) { for (p = n; p < 3; p++) { for (q = p; q < 3; q++) { arg = delij[n] * delij[p] * delij[q] * v3D[nv3]; arg1i3m = arg1i3m - arho3m[i][nv3] * arg; arg1j3m = arg1j3m + arho3m[j][nv3] * arg; nv3 = nv3 + 1; } arg = delij[n] * delij[p] * v2D[nv2]; arg1i2m = arg1i2m + arho2m[i][nv2] * arg; arg1j2m = arg1j2m + arho2m[j][nv2] * arg; nv2 = nv2 + 1; } arg1i1m = arg1i1m - arho1m[i][n] * delij[n]; arg1j1m = arg1j1m + arho1m[j][n] * delij[n]; arg3i3m = arg3i3m - arho3mb[i][n] * delij[n]; arg3j3m = arg3j3m + arho3mb[j][n] * delij[n]; } } // rho0 terms drho0dr1 = drhoa0j * sij; drho0dr2 = drhoa0i * sij; // rho1 terms a1 = 2 * sij / rij; drho1dr1 = a1 * (drhoa1j - rhoa1j / rij) * arg1i1; drho1dr2 = a1 * (drhoa1i - rhoa1i / rij) * arg1j1; a1 = 2.0 * sij / rij; for (m = 0; m < 3; m++) { drho1drm1[m] = a1 * rhoa1j * arho1[i][m]; drho1drm2[m] = -a1 * rhoa1i * arho1[j][m]; } // rho2 terms a2 = 2 * sij / rij2; drho2dr1 = a2 * (drhoa2j - 2 * rhoa2j / rij) * arg1i2 - 2.0 / 3.0 * arho2b[i] * drhoa2j * sij; drho2dr2 = a2 * (drhoa2i - 2 * rhoa2i / rij) * arg1j2 - 2.0 / 3.0 * arho2b[j] * drhoa2i * sij; a2 = 4 * sij / rij2; for (m = 0; m < 3; m++) { drho2drm1[m] = 0.0; drho2drm2[m] = 0.0; for (n = 0; n < 3; n++) { drho2drm1[m] = drho2drm1[m] + arho2[i][vind2D[m][n]] * delij[n]; drho2drm2[m] = drho2drm2[m] - arho2[j][vind2D[m][n]] * delij[n]; } drho2drm1[m] = a2 * rhoa2j * drho2drm1[m]; drho2drm2[m] = -a2 * rhoa2i * drho2drm2[m]; } // rho3 terms rij3 = rij * rij2; a3 = 2 * sij / rij3; a3a = 6.0 / 5.0 * sij / rij; drho3dr1 = a3 * (drhoa3j - 3 * rhoa3j / rij) * arg1i3 - a3a * (drhoa3j - rhoa3j / rij) * arg3i3; drho3dr2 = a3 * (drhoa3i - 3 * rhoa3i / rij) * arg1j3 - a3a * (drhoa3i - rhoa3i / rij) * arg3j3; a3 = 6 * sij / rij3; a3a = 6 * sij / (5 * rij); for (m = 0; m < 3; m++) { drho3drm1[m] = 0.0; drho3drm2[m] = 0.0; nv2 = 0; for (n = 0; n < 3; n++) { for (p = n; p < 3; p++) { arg = delij[n] * delij[p] * v2D[nv2]; drho3drm1[m] = drho3drm1[m] + arho3[i][vind3D[m][n][p]] * arg; drho3drm2[m] = drho3drm2[m] + arho3[j][vind3D[m][n][p]] * arg; nv2 = nv2 + 1; } } drho3drm1[m] = (a3 * drho3drm1[m] - a3a * arho3b[i][m]) * rhoa3j; drho3drm2[m] = (-a3 * drho3drm2[m] + a3a * arho3b[j][m]) * rhoa3i; } if (msmeamflag) { // rho1m terms a1 = 2 * sij / rij; drho1mdr1 = a1 * (drhoa1mj - rhoa1mj / rij) * arg1i1m; drho1mdr2 = a1 * (drhoa1mi - rhoa1mi / rij) * arg1j1m; drho1mdr1 *= -1.0; drho1mdr2 *= -1.0; a1 = 2.0 * sij / rij; for (m = 0; m < 3; m++) { drho1mdrm1[m] = a1 * rhoa1mj * arho1m[i][m]; drho1mdrm2[m] = -a1 * rhoa1mi * arho1m[j][m]; } // rho2m terms a2 = 2 * sij / rij2; drho2mdr1 = a2 * (drhoa2mj - 2 * rhoa2mj / rij) * arg1i2m - 2.0 / 3.0 * arho2mb[i] * drhoa2mj * sij; drho2mdr2 = a2 * (drhoa2mi - 2 * rhoa2mi / rij) * arg1j2m - 2.0 / 3.0 * arho2mb[j] * drhoa2mi * sij; a2 = 4 * sij / rij2; for (m = 0; m < 3; m++) { drho2mdrm1[m] = 0.0; drho2mdrm2[m] = 0.0; for (n = 0; n < 3; n++) { drho2mdrm1[m] += arho2m[i][vind2D[m][n]] * delij[n]; drho2mdrm2[m] -= arho2m[j][vind2D[m][n]] * delij[n]; } drho2mdrm1[m] = a2 * rhoa2mj * drho2mdrm1[m]; drho2mdrm2[m] = -a2 * rhoa2mi * drho2mdrm2[m]; } // rho3m terms rij3 = rij * rij2; a3 = 2 * sij / rij3; a3a = 6.0 / 5.0 * sij / rij; drho3mdr1 = a3 * (drhoa3mj - 3 * rhoa3mj / rij) * arg1i3m - a3a * (drhoa3mj - rhoa3mj / rij) * arg3i3m; drho3mdr2 = a3 * (drhoa3mi - 3 * rhoa3mi / rij) * arg1j3m - a3a * (drhoa3mi - rhoa3mi / rij) * arg3j3m; drho3mdr1 *= -1.0; drho3mdr2 *= -1.0; a3 = 6 * sij / rij3; a3a = 6 * sij / (5 * rij); for (m = 0; m < 3; m++) { drho3mdrm1[m] = 0.0; drho3mdrm2[m] = 0.0; nv2 = 0; for (n = 0; n < 3; n++) { for (p = n; p < 3; p++) { arg = delij[n] * delij[p] * v2D[nv2]; drho3mdrm1[m] += arho3m[i][vind3D[m][n][p]] * arg; drho3mdrm2[m] += arho3m[j][vind3D[m][n][p]] * arg; nv2 = nv2 + 1; } } drho3mdrm1[m] = (a3 * drho3mdrm1[m] - a3a * arho3mb[i][m]) * rhoa3mj; drho3mdrm2[m] = (-a3 * drho3mdrm2[m] + a3a * arho3mb[j][m]) * rhoa3mi; } } else { for (m = 0; m < 3; m++) { drho1mdrm1[m] = 0.0; drho1mdrm2[m] = 0.0; drho2mdrm1[m] = 0.0; drho2mdrm2[m] = 0.0; drho3mdrm1[m] = 0.0; drho3mdrm2[m] = 0.0; } } // compute derivatives of weighting functions t wrt rij // weighting functions t set to unity for MS-MEAM if (msmeamflag) { t1i = 1.0; t2i = 1.0; t3i = 1.0; t1j = 1.0; t2j = 1.0; t3j = 1.0; dt1dr1 = 0.0; dt1dr2 = 0.0; dt2dr1 = 0.0; dt2dr2 = 0.0; dt3dr1 = 0.0; dt3dr2 = 0.0; } else { t1i = t_ave[i][0]; t2i = t_ave[i][1]; t3i = t_ave[i][2]; t1j = t_ave[j][0]; t2j = t_ave[j][1]; t3j = t_ave[j][2]; if (ialloy == 1) { a1i = fdiv_zero(drhoa0j * sij, tsq_ave[i][0]); a1j = fdiv_zero(drhoa0i * sij, tsq_ave[j][0]); a2i = fdiv_zero(drhoa0j * sij, tsq_ave[i][1]); a2j = fdiv_zero(drhoa0i * sij, tsq_ave[j][1]); a3i = fdiv_zero(drhoa0j * sij, tsq_ave[i][2]); a3j = fdiv_zero(drhoa0i * sij, tsq_ave[j][2]); dt1dr1 = a1i * (t1mj - t1i * MathSpecial::square(t1mj)); dt1dr2 = a1j * (t1mi - t1j * MathSpecial::square(t1mi)); dt2dr1 = a2i * (t2mj - t2i * MathSpecial::square(t2mj)); dt2dr2 = a2j * (t2mi - t2j * MathSpecial::square(t2mi)); dt3dr1 = a3i * (t3mj - t3i * MathSpecial::square(t3mj)); dt3dr2 = a3j * (t3mi - t3j * MathSpecial::square(t3mi)); } else if (ialloy == 2) { dt1dr1 = 0.0; dt1dr2 = 0.0; dt2dr1 = 0.0; dt2dr2 = 0.0; dt3dr1 = 0.0; dt3dr2 = 0.0; } else { ai = 0.0; if (!iszero(rho0[i])) ai = drhoa0j * sij / rho0[i]; aj = 0.0; if (!iszero(rho0[j])) aj = drhoa0i * sij / rho0[j]; dt1dr1 = ai * (t1mj - t1i); dt1dr2 = aj * (t1mi - t1j); dt2dr1 = ai * (t2mj - t2i); dt2dr2 = aj * (t2mi - t2j); dt3dr1 = ai * (t3mj - t3i); dt3dr2 = aj * (t3mi - t3j); } } // Compute derivatives of total density wrt rij, sij and rij(3) get_shpfcn(lattce_meam[elti][elti], stheta_meam[elti][elti], ctheta_meam[elti][elti], shpi); get_shpfcn(lattce_meam[eltj][eltj], stheta_meam[elti][elti], ctheta_meam[elti][elti], shpj); if (msmeamflag) { drhodr1 = dgamma1[i] * drho0dr1 + dgamma2[i] * (dt1dr1 * rho1[i] + t1i * (drho1dr1 - drho1mdr1) + dt2dr1 * rho2[i] + t2i * (drho2dr1 - drho2mdr1) + dt3dr1 * rho3[i] + t3i * (drho3dr1 - drho3mdr1)) - dgamma3[i] * (shpi[0] * dt1dr1 + shpi[1] * dt2dr1 + shpi[2] * dt3dr1); drhodr2 = dgamma1[j] * drho0dr2 + dgamma2[j] * (dt1dr2 * rho1[j] + t1j * (drho1dr2 - drho1mdr2) + dt2dr2 * rho2[j] + t2j * (drho2dr2 - drho2mdr2) + dt3dr2 * rho3[j] + t3j * (drho3dr2 - drho3mdr2)) - dgamma3[j] * (shpj[0] * dt1dr2 + shpj[1] * dt2dr2 + shpj[2] * dt3dr2); for (m = 0; m < 3; m++) { drhodrm1[m] = 0.0; drhodrm2[m] = 0.0; drhodrm1[m] = dgamma2[i] * (t1i * (drho1drm1[m] - drho1mdrm1[m]) + t2i * (drho2drm1[m] - drho2mdrm1[m]) + t3i * (drho3drm1[m] - drho3mdrm1[m]) ); drhodrm2[m] = dgamma2[j] * (t1j * (drho1drm2[m] - drho1mdrm2[m]) + t2j * (drho2drm2[m] - drho2mdrm2[m]) + t3j * (drho3drm2[m] - drho3mdrm2[m]) ); } } else { drhodr1 = dgamma1[i] * drho0dr1 + dgamma2[i] * (dt1dr1 * rho1[i] + t1i * drho1dr1 + dt2dr1 * rho2[i] + t2i * drho2dr1 + dt3dr1 * rho3[i] + t3i * drho3dr1) - dgamma3[i] * (shpi[0] * dt1dr1 + shpi[1] * dt2dr1 + shpi[2] * dt3dr1); drhodr2 = dgamma1[j] * drho0dr2 + dgamma2[j] * (dt1dr2 * rho1[j] + t1j * drho1dr2 + dt2dr2 * rho2[j] + t2j * drho2dr2 + dt3dr2 * rho3[j] + t3j * drho3dr2) - dgamma3[j] * (shpj[0] * dt1dr2 + shpj[1] * dt2dr2 + shpj[2] * dt3dr2); for (m = 0; m < 3; m++) { drhodrm1[m] = 0.0; drhodrm2[m] = 0.0; drhodrm1[m] = dgamma2[i] * (t1i * drho1drm1[m] + t2i * drho2drm1[m] + t3i * drho3drm1[m]); drhodrm2[m] = dgamma2[j] * (t1j * drho1drm2[m] + t2j * drho2drm2[m] + t3j * drho3drm2[m]); } } // Compute derivatives wrt sij, but only if necessary if (!iszero(dscrfcn[fnoffset + jn])) { drho0ds1 = rhoa0j; drho0ds2 = rhoa0i; a1 = 2.0 / rij; a2 = 2.0 / rij2; a3 = 2.0 / rij3; a3a = 6.0 / (5.0 * rij); drho1ds1 = a1 * rhoa1j * arg1i1; drho1ds2 = a1 * rhoa1i * arg1j1; drho2ds1 = a2 * rhoa2j * arg1i2 - 2.0 / 3.0 * arho2b[i] * rhoa2j; drho2ds2 = a2 * rhoa2i * arg1j2 - 2.0 / 3.0 * arho2b[j] * rhoa2i; drho3ds1 = a3 * rhoa3j * arg1i3 - a3a * rhoa3j * arg3i3; drho3ds2 = a3 * rhoa3i * arg1j3 - a3a * rhoa3i * arg3j3; if (msmeamflag) { const double drho1mds1 = -a1 * rhoa1mj * arg1i1m; const double drho1mds2 = -a1 * rhoa1mi * arg1j1m; const double drho2mds1 = a2 * rhoa2mj * arg1i2m - 2.0 / 3.0 * arho2mb[i] * rhoa2mj; const double drho2mds2 = a2 * rhoa2mi * arg1j2m - 2.0 / 3.0 * arho2mb[j] * rhoa2mi; const double drho3mds1 = -a3 * rhoa3mj * arg1i3m + a3a * rhoa3mj * arg3i3m; const double drho3mds2 = -a3 * rhoa3mi * arg1j3m + a3a * rhoa3mi * arg3j3m; t1i = 1.0; t2i = 1.0; t3i = 1.0; t1j = 1.0; t2j = 1.0; t3j = 1.0; dt1dr1 = 0.0; dt1dr2 = 0.0; dt2dr1 = 0.0; dt2dr2 = 0.0; dt3dr1 = 0.0; dt3dr2 = 0.0; // these formulae are simplifed by substituting t=1, dt=0 from above drhods1 = dgamma1[i] * drho0ds1 + dgamma2[i] * ((drho1ds1 - drho1mds1) + (drho2ds1 - drho2mds1) + (drho3ds1 - drho3mds1)); drhods2 = dgamma1[j] * drho0ds2 + dgamma2[j] * ((drho1ds2 - drho1mds2) + (drho2ds2 - drho2mds2) + (drho3ds2 - drho3mds2)); } else { if (ialloy == 1) { a1i = fdiv_zero(rhoa0j, tsq_ave[i][0]); a1j = fdiv_zero(rhoa0i, tsq_ave[j][0]); a2i = fdiv_zero(rhoa0j, tsq_ave[i][1]); a2j = fdiv_zero(rhoa0i, tsq_ave[j][1]); a3i = fdiv_zero(rhoa0j, tsq_ave[i][2]); a3j = fdiv_zero(rhoa0i, tsq_ave[j][2]); dt1ds1 = a1i * (t1mj - t1i * MathSpecial::square(t1mj)); dt1ds2 = a1j * (t1mi - t1j * MathSpecial::square(t1mi)); dt2ds1 = a2i * (t2mj - t2i * MathSpecial::square(t2mj)); dt2ds2 = a2j * (t2mi - t2j * MathSpecial::square(t2mi)); dt3ds1 = a3i * (t3mj - t3i * MathSpecial::square(t3mj)); dt3ds2 = a3j * (t3mi - t3j * MathSpecial::square(t3mi)); } else if (ialloy == 2) { dt1ds1 = 0.0; dt1ds2 = 0.0; dt2ds1 = 0.0; dt2ds2 = 0.0; dt3ds1 = 0.0; dt3ds2 = 0.0; } else { ai = 0.0; if (!iszero(rho0[i])) ai = rhoa0j / rho0[i]; aj = 0.0; if (!iszero(rho0[j])) aj = rhoa0i / rho0[j]; dt1ds1 = ai * (t1mj - t1i); dt1ds2 = aj * (t1mi - t1j); dt2ds1 = ai * (t2mj - t2i); dt2ds2 = aj * (t2mi - t2j); dt3ds1 = ai * (t3mj - t3i); dt3ds2 = aj * (t3mi - t3j); } drhods1 = dgamma1[i] * drho0ds1 + dgamma2[i] * (dt1ds1 * rho1[i] + t1i * drho1ds1 + dt2ds1 * rho2[i] + t2i * drho2ds1 + dt3ds1 * rho3[i] + t3i * drho3ds1) - dgamma3[i] * (shpi[0] * dt1ds1 + shpi[1] * dt2ds1 + shpi[2] * dt3ds1); drhods2 = dgamma1[j] * drho0ds2 + dgamma2[j] * (dt1ds2 * rho1[j] + t1j * drho1ds2 + dt2ds2 * rho2[j] + t2j * drho2ds2 + dt3ds2 * rho3[j] + t3j * drho3ds2) - dgamma3[j] * (shpj[0] * dt1ds2 + shpj[1] * dt2ds2 + shpj[2] * dt3ds2); } } // Compute derivatives of energy wrt rij, sij and rij[3] // MS-MEAM affects phip dUdrij = phip * sij + frhop[i] * drhodr1 + frhop[j] * drhodr2; dUdsij = 0.0; if (!iszero(dscrfcn[fnoffset + jn])) { dUdsij = phi + frhop[i] * drhods1 + frhop[j] * drhods2; } for (m = 0; m < 3; m++) { dUdrijm[m] = frhop[i] * drhodrm1[m] + frhop[j] * drhodrm2[m]; } if (!isone(scaleij)) { dUdrij *= scaleij; dUdsij *= scaleij; dUdrijm[0] *= scaleij; dUdrijm[1] *= scaleij; dUdrijm[2] *= scaleij; } // Add the part of the force due to dUdrij and dUdsij force = dUdrij * recip + dUdsij * dscrfcn[fnoffset + jn]; for (m = 0; m < 3; m++) { forcem = delij[m] * force + dUdrijm[m]; f[i][m] = f[i][m] + forcem; f[j][m] = f[j][m] - forcem; } // Tabulate per-atom virial as symmetrized stress tensor if (vflag_either) { fi[0] = delij[0] * force + dUdrijm[0]; fi[1] = delij[1] * force + dUdrijm[1]; fi[2] = delij[2] * force + dUdrijm[2]; v[0] = -0.5 * (delij[0] * fi[0]); v[1] = -0.5 * (delij[1] * fi[1]); v[2] = -0.5 * (delij[2] * fi[2]); v[3] = -0.25 * (delij[0] * fi[1] + delij[1] * fi[0]); v[4] = -0.25 * (delij[0] * fi[2] + delij[2] * fi[0]); v[5] = -0.25 * (delij[1] * fi[2] + delij[2] * fi[1]); if (vflag_global) { for (m = 0; m < 6; m++) { virial[m] += 2.0*v[m]; } } if (vflag_atom) { for (m = 0; m < 6; m++) { vatom[i][m] += v[m]; vatom[j][m] += v[m]; } } } // Now compute forces on other atoms k due to change in sij if (iszero(sij) || isone(sij)) continue; //: cont jn loop double dxik(0), dyik(0), dzik(0); double dxjk(0), dyjk(0), dzjk(0); for (kn = 0; kn < numneigh_full; kn++) { k = firstneigh_full[kn]; eltk = fmap[type[k]]; if (k != j && eltk >= 0) { double xik, xjk, cikj, sikj, dfc, a; double dCikj1, dCikj2; double delc, rik2, rjk2; sij = scrfcn[jn+fnoffset] * fcpair[jn+fnoffset]; const double Cmax = Cmax_meam[elti][eltj][eltk]; const double Cmin = Cmin_meam[elti][eltj][eltk]; dsij1 = 0.0; dsij2 = 0.0; if (!iszero(sij) && !isone(sij)) { const double rbound = rij2 * ebound_meam[elti][eltj]; delc = Cmax - Cmin; dxjk = x[k][0] - x[j][0]; dyjk = x[k][1] - x[j][1]; dzjk = x[k][2] - x[j][2]; rjk2 = dxjk * dxjk + dyjk * dyjk + dzjk * dzjk; if (rjk2 <= rbound) { dxik = x[k][0] - x[i][0]; dyik = x[k][1] - x[i][1]; dzik = x[k][2] - x[i][2]; rik2 = dxik * dxik + dyik * dyik + dzik * dzik; if (rik2 <= rbound) { xik = rik2 / rij2; xjk = rjk2 / rij2; a = 1 - (xik - xjk) * (xik - xjk); if (!iszero(a)) { cikj = (2.0 * (xik + xjk) + a - 2.0) / a; if (cikj >= Cmin && cikj <= Cmax) { cikj = (cikj - Cmin) / delc; sikj = dfcut(cikj, dfc); dCfunc2(rij2, rik2, rjk2, dCikj1, dCikj2); a = sij / delc * dfc / sikj; dsij1 = a * dCikj1; dsij2 = a * dCikj2; } } } } } if (!iszero(dsij1) || !iszero(dsij2)) { force1 = dUdsij * dsij1; force2 = dUdsij * dsij2; f[i][0] += force1 * dxik; f[i][1] += force1 * dyik; f[i][2] += force1 * dzik; f[j][0] += force2 * dxjk; f[j][1] += force2 * dyjk; f[j][2] += force2 * dzjk; f[k][0] -= force1 * dxik + force2 * dxjk; f[k][1] -= force1 * dyik + force2 * dyjk; f[k][2] -= force1 * dzik + force2 * dzjk; // Tabulate per-atom virial as symmetrized stress tensor if (vflag_either) { fi[0] = force1 * dxik; fi[1] = force1 * dyik; fi[2] = force1 * dzik; fj[0] = force2 * dxjk; fj[1] = force2 * dyjk; fj[2] = force2 * dzjk; v[0] = -third * (dxik * fi[0] + dxjk * fj[0]); v[1] = -third * (dyik * fi[1] + dyjk * fj[1]); v[2] = -third * (dzik * fi[2] + dzjk * fj[2]); v[3] = -sixth * (dxik * fi[1] + dxjk * fj[1] + dyik * fi[0] + dyjk * fj[0]); v[4] = -sixth * (dxik * fi[2] + dxjk * fj[2] + dzik * fi[0] + dzjk * fj[0]); v[5] = -sixth * (dyik * fi[2] + dyjk * fj[2] + dzik * fi[1] + dzjk * fj[1]); if (vflag_global) { for (m = 0; m < 6; m++) { virial[m] += 3.0*v[m]; } } if (vflag_atom) { for (m = 0; m < 6; m++) { vatom[i][m] += v[m]; vatom[j][m] += v[m]; vatom[k][m] += v[m]; } } } } } // end of k loop } } } // end of j loop } }