/* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov 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 (triclinic) : Pieter in 't Veld (SNL) ------------------------------------------------------------------------- */ #include "mpi.h" #include "stdlib.h" #include "string.h" #include "stdio.h" #include "math.h" #include "domain_cuda.h" #include "style_region.h" #include "atom.h" #include "force.h" #include "update.h" #include "modify.h" #include "fix.h" #include "fix_deform.h" #include "region.h" #include "lattice.h" #include "comm.h" #include "memory.h" #include "error.h" #include "user_cuda.h" #include "domain_cu.h" using namespace LAMMPS_NS; #define BIG 1.0e20 #define SMALL 1.0e-4 #define DELTA 1 enum {NO_REMAP, X_REMAP, V_REMAP}; // same as fix_deform.cpp /* ---------------------------------------------------------------------- default is periodic ------------------------------------------------------------------------- */ DomainCuda::DomainCuda(LAMMPS* lmp) : Domain(lmp) { cuda = lmp->cuda; if(cuda == NULL) error->all(FLERR, "You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS.."); } /* ---------------------------------------------------------------------- */ void DomainCuda::init() { Domain::init(); if(not cuda->finished_run) { cuda->setDomainParams(); Cuda_Domain_Init(&cuda->shared_data); } } /* ---------------------------------------------------------------------- set global box params assumes boxlo/hi and triclinic tilts are already set ------------------------------------------------------------------------- */ void DomainCuda::set_global_box() { // one-time activation of CUDA // do it here, b/c is now too late for further package commands // activation must occur before any USER-CUDA class communicates with GPUs cuda->activate(); Domain::set_global_box(); if(not cuda->finished_run) { cuda->setDomainParams(); } } /* ---------------------------------------------------------------------- set lamda box params, only need be done one time assumes global box is defined and proc assignment has been made by comm for uppermost proc, insure subhi = 1.0 (in case round-off occurs) ------------------------------------------------------------------------- */ void DomainCuda::set_lamda_box() { Domain::set_lamda_box(); if(not cuda->finished_run) { cuda->setDomainParams(); } } /* ---------------------------------------------------------------------- set local subbox params assumes global box is defined and proc assignment has been made for uppermost proc, insure subhi = boxhi (in case round-off occurs) ------------------------------------------------------------------------- */ void DomainCuda::set_local_box() { Domain::set_local_box(); if(not cuda->finished_run) { // cuda->setDomainParams(); //Cuda_Domain_Init(&cuda->shared_data); } } /* ---------------------------------------------------------------------- reset global & local boxes due to global box boundary changes if shrink-wrapped, determine atom extent and reset boxlo/hi if shrink-wrapped and triclinic, perform shrink-wrap in box coords ------------------------------------------------------------------------- */ void DomainCuda::reset_box() { if(nonperiodic == 2) { // convert back to box coords for shrink-wrap operation if(triclinic) lamda2x(atom->nlocal); // compute extent of atoms on this proc double extent[3][2], all[3][2]; extent[2][0] = extent[1][0] = extent[0][0] = BIG; extent[2][1] = extent[1][1] = extent[0][1] = -BIG; double** x = atom->x; int nlocal = atom->nlocal; if(cuda->finished_setup && (!cuda->oncpu)) { extent[0][0] = cuda->extent[0]; extent[0][1] = cuda->extent[1]; extent[1][0] = cuda->extent[2]; extent[1][1] = cuda->extent[3]; extent[2][0] = cuda->extent[4]; extent[2][1] = cuda->extent[5]; } else for(int i = 0; i < nlocal; i++) { extent[0][0] = MIN(extent[0][0], x[i][0]); extent[0][1] = MAX(extent[0][1], x[i][0]); extent[1][0] = MIN(extent[1][0], x[i][1]); extent[1][1] = MAX(extent[1][1], x[i][1]); extent[2][0] = MIN(extent[2][0], x[i][2]); extent[2][1] = MAX(extent[2][1], x[i][2]); } // compute extent across all procs // flip sign of MIN to do it in one Allreduce MAX extent[0][0] = -extent[0][0]; extent[1][0] = -extent[1][0]; extent[2][0] = -extent[2][0]; MPI_Allreduce(extent, all, 6, MPI_DOUBLE, MPI_MAX, world); // in shrink-wrapped dims, set box by atom extent // if minimum set, enforce min box size settings if(triclinic == 0) { if(xperiodic == 0) { if(boundary[0][0] == 2) boxlo[0] = -all[0][0] - small[0]; else if(boundary[0][0] == 3) boxlo[0] = MIN(-all[0][0] - small[0], minxlo); if(boundary[0][1] == 2) boxhi[0] = all[0][1] + small[0]; else if(boundary[0][1] == 3) boxhi[0] = MAX(all[0][1] + small[0], minxhi); if(boxlo[0] > boxhi[0]) error->all(FLERR, "Illegal simulation box"); } if(yperiodic == 0) { if(boundary[1][0] == 2) boxlo[1] = -all[1][0] - small[1]; else if(boundary[1][0] == 3) boxlo[1] = MIN(-all[1][0] - small[1], minylo); if(boundary[1][1] == 2) boxhi[1] = all[1][1] + small[1]; else if(boundary[1][1] == 3) boxhi[1] = MAX(all[1][1] + small[1], minyhi); if(boxlo[1] > boxhi[1]) error->all(FLERR, "Illegal simulation box"); } if(zperiodic == 0) { if(boundary[2][0] == 2) boxlo[2] = -all[2][0] - small[2]; else if(boundary[2][0] == 3) boxlo[2] = MIN(-all[2][0] - small[2], minzlo); if(boundary[2][1] == 2) boxhi[2] = all[2][1] + small[2]; else if(boundary[2][1] == 3) boxhi[2] = MAX(all[2][1] + small[2], minzhi); if(boxlo[2] > boxhi[2]) error->all(FLERR, "Illegal simulation box"); } } else { double lo[3], hi[3]; if(xperiodic == 0) { lo[0] = -all[0][0]; lo[1] = 0.0; lo[2] = 0.0; Domain::lamda2x(lo, lo); hi[0] = all[0][1]; hi[1] = 0.0; hi[2] = 0.0; Domain::lamda2x(hi, hi); if(boundary[0][0] == 2) boxlo[0] = lo[0] - small[0]; else if(boundary[0][0] == 3) boxlo[0] = MIN(lo[0] - small[0], minxlo); if(boundary[0][1] == 2) boxhi[0] = hi[0] + small[0]; else if(boundary[0][1] == 3) boxhi[0] = MAX(hi[0] + small[0], minxhi); if(boxlo[0] > boxhi[0]) error->all(FLERR, "Illegal simulation box"); } if(yperiodic == 0) { lo[0] = 0.0; lo[1] = -all[1][0]; lo[2] = 0.0; Domain::lamda2x(lo, lo); hi[0] = 0.0; hi[1] = all[1][1]; hi[2] = 0.0; Domain::lamda2x(hi, hi); if(boundary[1][0] == 2) boxlo[1] = lo[1] - small[1]; else if(boundary[1][0] == 3) boxlo[1] = MIN(lo[1] - small[1], minylo); if(boundary[1][1] == 2) boxhi[1] = hi[1] + small[1]; else if(boundary[1][1] == 3) boxhi[1] = MAX(hi[1] + small[1], minyhi); if(boxlo[1] > boxhi[1]) error->all(FLERR, "Illegal simulation box"); //xy *= (boxhi[1]-boxlo[1]) / yprd; } if(zperiodic == 0) { lo[0] = 0.0; lo[1] = 0.0; lo[2] = -all[2][0]; Domain::lamda2x(lo, lo); hi[0] = 0.0; hi[1] = 0.0; hi[2] = all[2][1]; Domain::lamda2x(hi, hi); if(boundary[2][0] == 2) boxlo[2] = lo[2] - small[2]; else if(boundary[2][0] == 3) boxlo[2] = MIN(lo[2] - small[2], minzlo); if(boundary[2][1] == 2) boxhi[2] = hi[2] + small[2]; else if(boundary[2][1] == 3) boxhi[2] = MAX(hi[2] + small[2], minzhi); if(boxlo[2] > boxhi[2]) error->all(FLERR, "Illegal simulation box"); //xz *= (boxhi[2]-boxlo[2]) / xprd; //yz *= (boxhi[2]-boxlo[2]) / yprd; } } } set_global_box(); set_local_box(); if(not cuda->finished_run) { cuda->setDomainParams(); Cuda_Domain_Init(&cuda->shared_data); } // if shrink-wrapped, convert to lamda coords for new box // must re-invoke pbc() b/c x2lamda result can be outside 0,1 due to roundoff if(nonperiodic == 2 && triclinic) { x2lamda(atom->nlocal); pbc(); } } /* ---------------------------------------------------------------------- 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 DomainCuda::pbc() { if(cuda->finished_setup && (!cuda->oncpu)) { cuda->setDomainParams(); Cuda_Domain_PBC(&cuda->shared_data, deform_vremap, deform_groupbit, cuda->extent); return; } Domain::pbc(); } /* ---------------------------------------------------------------------- convert triclinic 0-1 lamda coords to box coords for all N atoms x = H lamda + x0; ------------------------------------------------------------------------- */ void DomainCuda::lamda2x(int n) { if(cuda->finished_setup && (!cuda->oncpu)) { Cuda_Domain_lamda2x(&cuda->shared_data, n); return; } Domain::lamda2x(n); } /* ---------------------------------------------------------------------- convert box coords to triclinic 0-1 lamda coords for all N atoms lamda = H^-1 (x - x0) ------------------------------------------------------------------------- */ void DomainCuda::x2lamda(int n) { if(cuda->finished_setup && (!cuda->oncpu)) { Cuda_Domain_x2lamda(&cuda->shared_data, n); return; } Domain::x2lamda(n); }