183 lines
5.2 KiB
C++
183 lines
5.2 KiB
C++
/* ----------------------------------------------------------------------
|
|
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.
|
|
------------------------------------------------------------------------- */
|
|
|
|
#include "string.h"
|
|
#include "stdlib.h"
|
|
#include "fix_gpu.h"
|
|
#include "atom.h"
|
|
#include "force.h"
|
|
#include "pair.h"
|
|
#include "respa.h"
|
|
#include "input.h"
|
|
#include "error.h"
|
|
#include "timer.h"
|
|
#include "modify.h"
|
|
#include "domain.h"
|
|
#include "universe.h"
|
|
#include "gpu_extra.h"
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
enum{GPU_FORCE, GPU_NEIGH};
|
|
|
|
extern int lmp_init_device(MPI_Comm world, MPI_Comm replica,
|
|
const int first_gpu, const int last_gpu,
|
|
const int gpu_mode, const double particle_split,
|
|
const int nthreads, const int t_per_atom);
|
|
extern void lmp_clear_device();
|
|
extern double lmp_gpu_forces(double **f, double **tor, double *eatom,
|
|
double **vatom, double *virial, double &ecoul);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
FixGPU::FixGPU(LAMMPS *lmp, int narg, char **arg) :
|
|
Fix(lmp, narg, arg)
|
|
{
|
|
if (narg < 7) error->all("Illegal fix gpu command");
|
|
|
|
if (strcmp(arg[1],"all") != 0)
|
|
error->all("Illegal fix gpu command");
|
|
|
|
int first_gpu, last_gpu;
|
|
|
|
if (strcmp(arg[3],"force") == 0)
|
|
_gpu_mode = GPU_FORCE;
|
|
else if (strcmp(arg[3],"force/neigh") == 0) {
|
|
_gpu_mode = GPU_NEIGH;
|
|
if (domain->triclinic)
|
|
error->all("Cannot use force/neigh with triclinic box.");
|
|
} else
|
|
error->all("Illegal fix gpu command.");
|
|
|
|
first_gpu = atoi(arg[4]);
|
|
last_gpu = atoi(arg[5]);
|
|
|
|
_particle_split = force->numeric(arg[6]);
|
|
if (_particle_split==0 || _particle_split>1)
|
|
error->all("Illegal fix gpu command.");
|
|
|
|
int nthreads = 1;
|
|
int threads_per_atom = -1;
|
|
if (narg == 9) {
|
|
if (strcmp(arg[7],"threads_per_atom") == 0)
|
|
threads_per_atom = atoi(arg[8]);
|
|
else if (strcmp(arg[7],"nthreads") == 0)
|
|
nthreads = atoi(arg[8]);
|
|
else
|
|
error->all("Illegal fix gpu command.");
|
|
} else if (narg != 7)
|
|
error->all("Illegal fix gpu command.");
|
|
|
|
if (nthreads < 1)
|
|
error->all("Illegal fix gpu command.");
|
|
|
|
#ifndef _OPENMP
|
|
if (nthreads > 1)
|
|
error->all("No OpenMP support compiled in.");
|
|
#endif
|
|
|
|
int gpu_flag = lmp_init_device(universe->uworld, world, first_gpu, last_gpu,
|
|
_gpu_mode, _particle_split, nthreads,
|
|
threads_per_atom);
|
|
GPU_EXTRA::check_flag(gpu_flag,error,world);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
FixGPU::~FixGPU()
|
|
{
|
|
lmp_clear_device();
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
int FixGPU::setmask()
|
|
{
|
|
int mask = 0;
|
|
mask |= POST_FORCE;
|
|
mask |= MIN_POST_FORCE;
|
|
return mask;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixGPU::init()
|
|
{
|
|
// Can only have 1 gpu fix that must be the first fix for a run
|
|
if ((void*)modify->fix[0] != (void*)this)
|
|
error->all("GPU is not the first fix for this run.");
|
|
// Hybrid cannot be used with force/neigh option
|
|
if (_gpu_mode == GPU_NEIGH)
|
|
if (force->pair_match("hybrid",1) != NULL ||
|
|
force->pair_match("hybrid/overlay",1) != NULL)
|
|
error->all("Cannot use pair hybrid with GPU neighbor builds.");
|
|
if (_particle_split < 0)
|
|
if (force->pair_match("hybrid",1) != NULL ||
|
|
force->pair_match("hybrid/overlay",1) != NULL)
|
|
error->all("Fix gpu split must be positive for hybrid pair styles.");
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixGPU::setup(int vflag)
|
|
{
|
|
post_force(vflag);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixGPU::min_setup(int vflag)
|
|
{
|
|
post_force(vflag);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixGPU::post_force(int vflag)
|
|
{
|
|
timer->stamp();
|
|
double lvirial[6];
|
|
for (int i = 0; i < 6; i++) lvirial[i] = 0.0;
|
|
double my_eng = lmp_gpu_forces(atom->f, atom->torque, force->pair->eatom,
|
|
force->pair->vatom, lvirial,
|
|
force->pair->eng_coul);
|
|
|
|
force->pair->eng_vdwl += my_eng;
|
|
force->pair->virial[0] += lvirial[0];
|
|
force->pair->virial[1] += lvirial[1];
|
|
force->pair->virial[2] += lvirial[2];
|
|
force->pair->virial[3] += lvirial[3];
|
|
force->pair->virial[4] += lvirial[4];
|
|
force->pair->virial[5] += lvirial[5];
|
|
|
|
if (force->pair->vflag_fdotr) force->pair->virial_compute();
|
|
timer->stamp(TIME_PAIR);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixGPU::min_post_force(int vflag)
|
|
{
|
|
post_force(vflag);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
double FixGPU::memory_usage()
|
|
{
|
|
double bytes = 0.0;
|
|
// Memory usage currently returned by pair routine
|
|
return bytes;
|
|
}
|
|
|