/* ---------------------------------------------------------------------- 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. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author : Axel Kohlmeyer (Temple U) ------------------------------------------------------------------------- */ #include "accelerator_omp.h" #include "atom.h" #include "error.h" #include "omp_compat.h" #include using namespace LAMMPS_NS; typedef struct { double x, y, z; } dbl3_t; /* ---------------------------------------------------------------------- enforce PBC and modify box image flags for each atom called every reneighboring and by other commands that change atoms resulting coord must satisfy lo <= coord < hi MAX is important since coord - prd < lo can happen when coord = hi if fix deform, remap velocity of fix group atoms by box edge velocities for triclinic, atoms must be in lamda coords (0-1) before pbc is called image = 10 bits for each dimension increment/decrement in wrap-around fashion ------------------------------------------------------------------------- */ void DomainOMP::pbc() { const int nlocal = atom->nlocal; if (!nlocal) return; // verify owned atoms have valid numerical coords // may not if computed pairwise force between 2 atoms at same location const double *_noalias const coord = atom->x[0]; // NOLINT const int n3 = 3 * nlocal; int flag = 0; #if defined(_OPENMP) // clang-format off #pragma omp parallel for LMP_DEFAULT_NONE schedule(static) reduction(+:flag) #endif // clang-format on for (int i = 0; i < n3; i++) if (!std::isfinite(coord[i])) flag = 1; if (flag) error->one(FLERR, "Non-numeric atom coords - simulation unstable"); auto *_noalias const x = (dbl3_t *) atom->x[0]; auto *_noalias const v = (dbl3_t *) atom->v[0]; const double *_noalias const lo = (triclinic == 0) ? boxlo : boxlo_lamda; const double *_noalias const hi = (triclinic == 0) ? boxhi : boxhi_lamda; const double *_noalias const period = (triclinic == 0) ? prd : prd_lamda; const int *_noalias const mask = atom->mask; imageint *_noalias const image = atom->image; #if defined(_OPENMP) #pragma omp parallel for LMP_DEFAULT_NONE schedule(static) #endif for (int i = 0; i < nlocal; i++) { imageint idim, otherdims; if (xperiodic) { if (x[i].x < lo[0]) { x[i].x += period[0]; if (deform_vremap && mask[i] & deform_groupbit) v[i].x += h_rate[0]; idim = image[i] & IMGMASK; otherdims = image[i] ^ idim; idim--; idim &= IMGMASK; image[i] = otherdims | idim; } if (x[i].x >= hi[0]) { x[i].x -= period[0]; x[i].x = MAX(x[i].x, lo[0]); if (deform_vremap && mask[i] & deform_groupbit) v[i].x -= h_rate[0]; idim = image[i] & IMGMASK; otherdims = image[i] ^ idim; idim++; idim &= IMGMASK; image[i] = otherdims | idim; } } if (yperiodic) { if (x[i].y < lo[1]) { x[i].y += period[1]; if (deform_vremap && mask[i] & deform_groupbit) { v[i].x += h_rate[5]; v[i].y += h_rate[1]; } idim = (image[i] >> IMGBITS) & IMGMASK; otherdims = image[i] ^ (idim << IMGBITS); idim--; idim &= IMGMASK; image[i] = otherdims | (idim << IMGBITS); } if (x[i].y >= hi[1]) { x[i].y -= period[1]; x[i].y = MAX(x[i].y, lo[1]); if (deform_vremap && mask[i] & deform_groupbit) { v[i].x -= h_rate[5]; v[i].y -= h_rate[1]; } idim = (image[i] >> IMGBITS) & IMGMASK; otherdims = image[i] ^ (idim << IMGBITS); idim++; idim &= IMGMASK; image[i] = otherdims | (idim << IMGBITS); } } if (zperiodic) { if (x[i].z < lo[2]) { x[i].z += period[2]; if (deform_vremap && mask[i] & deform_groupbit) { v[i].x += h_rate[4]; v[i].y += h_rate[3]; v[i].z += h_rate[2]; } idim = image[i] >> IMG2BITS; otherdims = image[i] ^ (idim << IMG2BITS); idim--; idim &= IMGMASK; image[i] = otherdims | (idim << IMG2BITS); } if (x[i].z >= hi[2]) { x[i].z -= period[2]; x[i].z = MAX(x[i].z, lo[2]); if (deform_vremap && mask[i] & deform_groupbit) { v[i].x -= h_rate[4]; v[i].y -= h_rate[3]; v[i].z -= h_rate[2]; } idim = image[i] >> IMG2BITS; otherdims = image[i] ^ (idim << IMG2BITS); idim++; idim &= IMGMASK; image[i] = otherdims | (idim << IMG2BITS); } } } } /* ---------------------------------------------------------------------- convert triclinic 0-1 lamda coords to box coords for all N atoms x = H lamda + x0; ------------------------------------------------------------------------- */ void DomainOMP::lamda2x(int n) { const int num = n; if (!n) return; auto *_noalias const x = (dbl3_t *) atom->x[0]; #if defined(_OPENMP) #pragma omp parallel for LMP_DEFAULT_NONE schedule(static) #endif for (int i = 0; i < num; i++) { x[i].x = h[0] * x[i].x + h[5] * x[i].y + h[4] * x[i].z + boxlo[0]; x[i].y = h[1] * x[i].y + h[3] * x[i].z + boxlo[1]; x[i].z = h[2] * x[i].z + boxlo[2]; } } /* ---------------------------------------------------------------------- convert box coords to triclinic 0-1 lamda coords for all N atoms lamda = H^-1 (x - x0) ------------------------------------------------------------------------- */ void DomainOMP::x2lamda(int n) { const int num = n; if (!n) return; auto *_noalias const x = (dbl3_t *) atom->x[0]; #if defined(_OPENMP) #pragma omp parallel for LMP_DEFAULT_NONE schedule(static) #endif for (int i = 0; i < num; i++) { double delta0 = x[i].x - boxlo[0]; double delta1 = x[i].y - boxlo[1]; double delta2 = x[i].z - boxlo[2]; x[i].x = h_inv[0] * delta0 + h_inv[5] * delta1 + h_inv[4] * delta2; x[i].y = h_inv[1] * delta1 + h_inv[3] * delta2; x[i].z = h_inv[2] * delta2; } }