Merge pull request #2999 from akohlmey/maintenance-2021-09-29

Maintenance fixes for the stable release
This commit is contained in:
Axel Kohlmeyer
2021-11-09 15:11:19 -05:00
committed by GitHub
43 changed files with 686 additions and 433 deletions

View File

@ -7,8 +7,9 @@ endif()
option(DOWNLOAD_EIGEN3 "Download Eigen3 instead of using an already installed one)" ${DOWNLOAD_EIGEN3_DEFAULT})
if(DOWNLOAD_EIGEN3)
message(STATUS "Eigen3 download requested - we will build our own")
set(EIGEN3_URL "https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz" CACHE STRING "URL for Eigen3 tarball")
set(EIGEN3_MD5 "609286804b0f79be622ccf7f9ff2b660" CACHE STRING "MD5 checksum of Eigen3 tarball")
set(EIGEN3_URL "https://download.lammps.org/thirdparty/eigen-3.4.0.tar.gz" CACHE STRING "URL for Eigen3 tarball")
set(EIGEN3_MD5 "4c527a9171d71a72a9d4186e65bea559" CACHE STRING "MD5 checksum of Eigen3 tarball")
mark_as_advanced(EIGEN3_URL)
mark_as_advanced(EIGEN3_MD5)
include(ExternalProject)

View File

@ -230,7 +230,7 @@ $(VENV):
)
$(MATHJAX):
@git clone -b 3.2.0 -c advice.detachedHead=0 --depth 1 git://github.com/mathjax/MathJax.git $@
@git clone -b 3.2.0 -c advice.detachedHead=0 --depth 1 https://github.com/mathjax/MathJax.git $@
$(ANCHORCHECK): $(VENV)
@( \

View File

@ -137,9 +137,9 @@ changed. How to do this depends on the build system you are using.
.. admonition:: Git protocols
:class: note
The servers at github.com support the "git://" and "https://" access
protocols for anonymous, read-only access. If you have a suitably
configured GitHub account, you may also use SSH protocol with the
The servers at github.com support the "https://" access protocol for
anonymous, read-only access. If you have a suitably configured GitHub
account, you may also use SSH protocol with the
URL "git@github.com:lammps/lammps.git".
The LAMMPS GitHub project is currently managed by Axel Kohlmeyer

View File

@ -16,7 +16,7 @@ source code design, the program structure, the spatial decomposition
approach, the neighbor finding, basic communications algorithms, and how
users and developers have contributed to LAMMPS is:
`LAMMPS - A flexible simulation tool for particle-based materials modeling at the atomic, meso, and continuum scales, Comp. Phys. Comm. (accepted 09/2021), DOI:10.1016/j.cpc.2021.108171 <https://doi.org/10.1016/j.cpc.2021.108171>`_
`LAMMPS - A flexible simulation tool for particle-based materials modeling at the atomic, meso, and continuum scales, Comp. Phys. Comm. 271, 108171 (2022) <https://doi.org/10.1016/j.cpc.2021.108171>`_
So a project using LAMMPS or a derivative application that uses LAMMPS
as a simulation engine should cite this paper. The paper is expected to

View File

@ -1011,7 +1011,9 @@ can be disabled with the :code:`checksum` parameter.
Restrictions
""""""""""""
none
*dump_modify sort* is not supported for dumps of groups containing
more than 2 billion atoms.
Related commands
""""""""""""""""

View File

@ -310,7 +310,7 @@ Forschungszentrum Juelich.
The library is available for download at "http://scafacos.de" or can
be cloned from the git-repository
"git://github.com/scafacos/scafacos.git".
"https://github.com/scafacos/scafacos.git".
In order to use this KSpace style, you must download and build the
ScaFaCoS library, then build LAMMPS with the SCAFACOS package

View File

@ -1,6 +1,6 @@
Sphinx==4.0.3
Sphinx==4.2.0
sphinxcontrib-spelling==7.2.1
git+git://github.com/akohlmey/sphinx-fortran@parallel-read
git+https://github.com/akohlmey/sphinx-fortran@parallel-read
sphinx_tabs==3.2.0
breathe==4.31.0
Pygments==2.10.0

View File

@ -18,7 +18,7 @@
#endif
__kernel void kernel_cast_x(__global numtyp4 *restrict x_type,
const __global double *restrict x,
const __global numtyp *restrict x,
const __global int *restrict type,
const int nall) {
int ii=GLOBAL_ID_X;

View File

@ -475,7 +475,7 @@ class Atom {
UCL_Vector<numtyp,numtyp> v;
#ifdef GPU_CAST
UCL_Vector<double,double> x_cast;
UCL_Vector<numtyp,numtyp> x_cast;
UCL_Vector<int,int> type_cast;
#endif

View File

@ -1039,10 +1039,18 @@ Device<PRECISION,ACC_PRECISION> global_device;
using namespace LAMMPS_AL;
bool lmp_has_gpu_device()
// check if a suitable GPU is present.
// for mixed and double precision GPU library compilation
// also the GPU needs to support double precision.
bool lmp_has_compatible_gpu_device()
{
UCL_Device gpu;
return (gpu.num_platforms() > 0);
bool compatible_gpu = gpu.num_platforms() > 0;
#if defined(_SINGLE_DOUBLE) || defined(_DOUBLE_DOUBLE)
if (compatible_gpu && !gpu.double_precision(0))
compatible_gpu = false;
#endif
return compatible_gpu;
}
std::string lmp_gpu_device_info()

View File

@ -82,9 +82,9 @@ __kernel void k_zbl(const __global numtyp4 *restrict x_,
const __global numtyp4 *restrict coeff1,
const __global numtyp4 *restrict coeff2,
const __global numtyp4 *restrict coeff3,
const double cut_globalsq,
const double cut_innersq,
const double cut_inner,
const numtyp cut_globalsq,
const numtyp cut_innersq,
const numtyp cut_inner,
const int lj_types,
const __global int *dev_nbor,
const __global int *dev_packed,
@ -174,9 +174,9 @@ __kernel void k_zbl_fast(const __global numtyp4 *restrict x_,
const __global numtyp4 *restrict coeff1_in,
const __global numtyp4 *restrict coeff2_in,
const __global numtyp4 *restrict coeff3_in,
const double cut_globalsq,
const double cut_innersq,
const double cut_inner,
const numtyp cut_globalsq,
const numtyp cut_innersq,
const numtyp cut_inner,
const __global int *dev_nbor,
const __global int *dev_packed,
__global acctyp4 *restrict ans,

View File

@ -67,9 +67,9 @@ class ZBL : public BaseAtomic<numtyp, acctyp> {
/// If atom type constants fit in shared memory, use fast kernels
bool shared_types;
double _cut_globalsq;
double _cut_innersq;
double _cut_inner;
numtyp _cut_globalsq;
numtyp _cut_innersq;
numtyp _cut_inner;
/// Number of atom types
int _lj_types;

View File

@ -17,11 +17,12 @@ parser = ArgumentParser(prog='Install.py',
# settings
version = '3.3.9'
version = '3.4.0'
tarball = "eigen.tar.gz"
# known checksums for different Eigen versions. used to validate the download.
checksums = { \
'3.4.0' : '4c527a9171d71a72a9d4186e65bea559', \
'3.3.9' : '609286804b0f79be622ccf7f9ff2b660', \
'3.3.7' : '9e30f67e8531477de4117506fe44669b' \
}
@ -35,7 +36,7 @@ Syntax from src dir: make lib-smd args="-b"
Syntax from lib dir: python Install.py -b
or: python Install.py -p /usr/include/eigen3"
or: python Install.py -v 3.3.7 -b
or: python Install.py -v 3.4.0 -b
Example:
@ -77,7 +78,7 @@ if pathflag:
if buildflag:
print("Downloading Eigen ...")
eigentar = os.path.join(homepath, tarball)
url = "https://gitlab.com/libeigen/eigen/-/archive/%s/eigen-%s.tar.gz" % (version,version)
url = "https://download.lammps.org/thirdparty/eigen-%s.tar.gz" % version
geturl(url, eigentar)
# verify downloaded archive integrity via md5 checksum, if known.

View File

@ -26,6 +26,8 @@
#error "Unsupported QE coupling API. Want API version 1."
#endif
// we need to pass an MPI communicator to the LAMMPS library interface
#define LAMMPS_LIB_MPI
#include "library.h"
static const char delim[] = " \t\n\r";
@ -67,8 +69,8 @@ int main(int argc, char **argv)
#if 1 // AK: temporary hack
if ( qmmmcfg.nmm != 2 ) {
if (me == 0) {
fprintf( stderr, "\n Error in the number of processors for MM code"
"\n for the time being only two processor are allowed\n");
fprintf( stderr, "\n Error in the number of processors for the MM code.\n"
" Currently only requesting 2 MM processors is allowed.\n");
}
MPI_Finalize();
return -1;

View File

@ -176,20 +176,20 @@ void AngleGaussian::compute(int eflag, int vflag)
void AngleGaussian::allocate()
{
allocated = 1;
int n = atom->nangletypes;
int n = atom->nangletypes+1;
memory->create(nterms,n+1,"angle:nterms");
memory->create(angle_temperature,n+1,"angle:angle_temperature");
memory->create(nterms,n,"angle:nterms");
memory->create(angle_temperature,n,"angle:angle_temperature");
alpha = new double *[n+1];
width = new double *[n+1];
theta0 = new double *[n+1];
memset(alpha,0,sizeof(double)*(n+1));
memset(width,0,sizeof(double)*(n+1));
memset(theta0,0,sizeof(double)*(n+1));
alpha = new double*[n];
width = new double*[n];
theta0 = new double*[n];
memset(alpha,0,sizeof(double *)*n);
memset(width,0,sizeof(double *)*n);
memset(theta0,0,sizeof(double *)*n);
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
memory->create(setflag,n,"angle:setflag");
memset(setflag,0,sizeof(int)*n);
}
/* ----------------------------------------------------------------------

View File

@ -14,8 +14,6 @@
#include "bond_gaussian.h"
#include <cmath>
#include <cstring>
#include "atom.h"
#include "neighbor.h"
#include "comm.h"
@ -24,6 +22,8 @@
#include "memory.h"
#include "error.h"
#include <cmath>
#include <cstring>
using namespace LAMMPS_NS;
using namespace MathConst;
@ -131,20 +131,20 @@ void BondGaussian::compute(int eflag, int vflag)
void BondGaussian::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
int n = atom->nbondtypes+1;
memory->create(nterms,n+1,"bond:nterms");
memory->create(bond_temperature,n+1,"bond:bond_temperature");
memory->create(nterms,n,"bond:nterms");
memory->create(bond_temperature,n,"bond:bond_temperature");
alpha = new double *[n+1];
width = new double *[n+1];
r0 = new double *[n+1];
memset(alpha,0,sizeof(double)*(n+1));
memset(width,0,sizeof(double)*(n+1));
memset(r0,0,sizeof(double)*(n+1));
alpha = new double *[n];
width = new double *[n];
r0 = new double *[n];
memset(alpha,0,sizeof(double *)*n);
memset(width,0,sizeof(double *)*n);
memset(r0,0,sizeof(double *)*n);
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
memory->create(setflag,n,"bond:setflag");
memset(setflag,0,sizeof(int)*n);
}
/* ----------------------------------------------------------------------

View File

@ -31,7 +31,6 @@
#include "neigh_request.h"
#include "neighbor.h"
#include "potential_file_reader.h"
#include "tokenizer.h"
#include <cmath>
#include <cstring>
@ -59,6 +58,7 @@ PairDRIP::PairDRIP(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
restartinfo = 0;
one_coeff = 1;
manybody_flag = 1;
centroidstressflag = CENTROID_NOTAVAIL;
unit_convert_flag = utils::get_supported_conversions(utils::ENERGY);
@ -241,17 +241,17 @@ void PairDRIP::read_file(char *filename)
nparams++;
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
if (comm->me != 0) {
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
}
MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world);
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
if (comm->me != 0) {
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
}
MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world);
memory->destroy(elem2param);
memory->create(elem2param, nelements, nelements, "pair:elem2param");
for (int i = 0; i < nelements; i++) {
@ -259,7 +259,7 @@ void PairDRIP::read_file(char *filename)
int n = -1;
for (int m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement) {
if (n >= 0) error->all(FLERR, "Potential file has duplicate entry");
if (n >= 0) error->all(FLERR, "DRIP potential file has duplicate entry");
n = m;
}
}

View File

@ -142,8 +142,8 @@ void PairILPGrapheneHBN::allocate()
void PairILPGrapheneHBN::settings(int narg, char **arg)
{
if (narg < 1 || narg > 2) error->all(FLERR, "Illegal pair_style command");
if (strcmp(force->pair_style, "hybrid/overlay") != 0)
error->all(FLERR, "ERROR: requires hybrid/overlay pair_style");
if (!utils::strmatch(force->pair_style, "^hybrid/overlay"))
error->all(FLERR, "Pair style ilp/graphene/hbn must be used as sub-style with hybrid/overlay");
cut_global = utils::numeric(FLERR, arg[0], false, lmp);
if (narg == 2) tap_flag = utils::numeric(FLERR, arg[1], false, lmp);
@ -273,16 +273,17 @@ void PairILPGrapheneHBN::read_file(char *filename)
nparams++;
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
if (comm->me != 0) {
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
}
MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world);
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
if (comm->me != 0) {
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
}
MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world);
memory->destroy(elem2param);
memory->destroy(cutILPsq);
memory->create(elem2param, nelements, nelements, "pair:elem2param");
@ -292,7 +293,7 @@ void PairILPGrapheneHBN::read_file(char *filename)
int n = -1;
for (int m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement) {
if (n >= 0) error->all(FLERR, "ILP Potential file has duplicate entry");
if (n >= 0) error->all(FLERR, "ILP potential file has duplicate entry");
n = m;
}
}

View File

@ -34,7 +34,6 @@
#include "neigh_request.h"
#include "neighbor.h"
#include "potential_file_reader.h"
#include "tokenizer.h"
#include <cmath>
#include <cstring>
@ -142,8 +141,8 @@ void PairKolmogorovCrespiFull::allocate()
void PairKolmogorovCrespiFull::settings(int narg, char **arg)
{
if (narg < 1 || narg > 2) error->all(FLERR, "Illegal pair_style command");
if (strcmp(force->pair_style, "hybrid/overlay") != 0)
error->all(FLERR, "ERROR: requires hybrid/overlay pair_style");
if (!utils::strmatch(force->pair_style, "^hybrid/overlay"))
error->all(FLERR, "Pair style kolmogorov/crespi/full must be used as sub-style with hybrid/overlay");
cut_global = utils::numeric(FLERR, arg[0], false, lmp);
if (narg == 2) tap_flag = utils::numeric(FLERR, arg[1], false, lmp);
@ -270,17 +269,17 @@ void PairKolmogorovCrespiFull::read_file(char *filename)
nparams++;
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
if (comm->me != 0) {
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
}
MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world);
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
if (comm->me != 0) {
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
}
MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world);
memory->destroy(elem2param);
memory->destroy(cutKCsq);
memory->create(elem2param, nelements, nelements, "pair:elem2param");
@ -290,7 +289,7 @@ void PairKolmogorovCrespiFull::read_file(char *filename)
int n = -1;
for (int m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement) {
if (n >= 0) error->all(FLERR, "KC Potential file has duplicate entry");
if (n >= 0) error->all(FLERR, "KC potential file has duplicate entry");
n = m;
}
}

View File

@ -68,14 +68,14 @@ void BondClass2Kokkos<DeviceType>::compute(int eflag_in, int vflag_in)
//if(k_eatom.extent(0)<maxeatom) { // won't work without adding zero functor
memoryKK->destroy_kokkos(k_eatom,eatom);
memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"improper:eatom");
d_eatom = k_eatom.template view<DeviceType>();
d_eatom = k_eatom.template view<KKDeviceType>();
//}
}
if (vflag_atom) {
//if(k_vatom.extent(0)<maxvatom) { // won't work without adding zero functor
memoryKK->destroy_kokkos(k_vatom,vatom);
memoryKK->create_kokkos(k_vatom,vatom,maxvatom,"improper:vatom");
d_vatom = k_vatom.template view<DeviceType>();
d_vatom = k_vatom.template view<KKDeviceType>();
//}
}
@ -210,10 +210,10 @@ void BondClass2Kokkos<DeviceType>::coeff(int narg, char **arg)
BondClass2::coeff(narg, arg);
int n = atom->nbondtypes;
Kokkos::DualView<F_FLOAT*,DeviceType> k_k2("BondClass2::k2",n+1);
Kokkos::DualView<F_FLOAT*,DeviceType> k_k3("BondClass2::k3",n+1);
Kokkos::DualView<F_FLOAT*,DeviceType> k_k4("BondClass2::k4",n+1);
Kokkos::DualView<F_FLOAT*,DeviceType> k_r0("BondClass2::r0",n+1);
typename AT::tdual_ffloat_1d k_k2("BondClass2::k2",n+1);
typename AT::tdual_ffloat_1d k_k3("BondClass2::k3",n+1);
typename AT::tdual_ffloat_1d k_k4("BondClass2::k4",n+1);
typename AT::tdual_ffloat_1d k_r0("BondClass2::r0",n+1);
d_k2 = k_k2.template view<DeviceType>();
d_k3 = k_k3.template view<DeviceType>();
@ -247,10 +247,10 @@ void BondClass2Kokkos<DeviceType>::read_restart(FILE *fp)
BondClass2::read_restart(fp);
int n = atom->nbondtypes;
Kokkos::DualView<F_FLOAT*,DeviceType> k_k2("BondClass2::k2",n+1);
Kokkos::DualView<F_FLOAT*,DeviceType> k_k3("BondClass2::k3",n+1);
Kokkos::DualView<F_FLOAT*,DeviceType> k_k4("BondClass2::k4",n+1);
Kokkos::DualView<F_FLOAT*,DeviceType> k_r0("BondClass2::r0",n+1);
typename AT::tdual_ffloat_1d k_k2("BondClass2::k2",n+1);
typename AT::tdual_ffloat_1d k_k3("BondClass2::k3",n+1);
typename AT::tdual_ffloat_1d k_k4("BondClass2::k4",n+1);
typename AT::tdual_ffloat_1d k_r0("BondClass2::r0",n+1);
d_k2 = k_k2.template view<DeviceType>();
d_k3 = k_k3.template view<DeviceType>();

View File

@ -67,10 +67,11 @@ class BondClass2Kokkos : public BondClass2 {
typename Kokkos::View<double*[3],typename AT::t_f_array::array_layout,typename KKDevice<DeviceType>::value,Kokkos::MemoryTraits<Kokkos::Atomic> > f;
typename AT::t_int_2d bondlist;
Kokkos::DualView<E_FLOAT*,Kokkos::LayoutRight,DeviceType> k_eatom;
Kokkos::DualView<F_FLOAT*[6],Kokkos::LayoutRight,DeviceType> k_vatom;
Kokkos::View<E_FLOAT*,Kokkos::LayoutRight,typename KKDevice<DeviceType>::value,Kokkos::MemoryTraits<Kokkos::Atomic> > d_eatom;
Kokkos::View<F_FLOAT*[6],Kokkos::LayoutRight,typename KKDevice<DeviceType>::value,Kokkos::MemoryTraits<Kokkos::Atomic> > d_vatom;
typedef typename KKDevice<DeviceType>::value KKDeviceType;
Kokkos::DualView<E_FLOAT*,Kokkos::LayoutRight,KKDeviceType> k_eatom;
Kokkos::DualView<F_FLOAT*[6],Kokkos::LayoutRight,KKDeviceType> k_vatom;
Kokkos::View<E_FLOAT*,Kokkos::LayoutRight,KKDeviceType,Kokkos::MemoryTraits<Kokkos::Atomic> > d_eatom;
Kokkos::View<F_FLOAT*[6],Kokkos::LayoutRight,KKDeviceType,Kokkos::MemoryTraits<Kokkos::Atomic> > d_vatom;
int nlocal,newton_bond;
int eflag,vflag;

View File

@ -173,8 +173,6 @@ void ComputeOrientOrderAtomKokkos<DeviceType>::compute_peratom()
x = atomKK->k_x.view<DeviceType>();
mask = atomKK->k_mask.view<DeviceType>();
Kokkos::deep_copy(d_qnm,{0.0,0.0});
int vector_length_default = 1;
int team_size_default = 1;
if (!host_flag)
@ -185,6 +183,8 @@ void ComputeOrientOrderAtomKokkos<DeviceType>::compute_peratom()
if (chunk_size > inum - chunk_offset)
chunk_size = inum - chunk_offset;
Kokkos::deep_copy(d_qnm,{0.0,0.0});
//Neigh
{
int vector_length = vector_length_default;
@ -286,7 +286,7 @@ void ComputeOrientOrderAtomKokkos<DeviceType>::operator() (TagComputeOrientOrder
const int i = d_ilist[ii + chunk_offset];
const int ncount = d_ncount(ii);
// if not nnn neighbors, order parameter = 0;
// if not nnn neighbors, order parameter = 0
if ((ncount == 0) || (ncount < nnn)) {
for (int jj = 0; jj < ncol; jj++)
@ -316,7 +316,7 @@ void ComputeOrientOrderAtomKokkos<DeviceType>::operator() (TagComputeOrientOrder
const int ncount = d_ncount(ii);
if (jj >= ncount) return;
// if not nnn neighbors, order parameter = 0;
// if not nnn neighbors, order parameter = 0
if ((ncount == 0) || (ncount < nnn))
return;
@ -328,6 +328,12 @@ template<class DeviceType>
KOKKOS_INLINE_FUNCTION
void ComputeOrientOrderAtomKokkos<DeviceType>::operator() (TagComputeOrientOrderAtomBOOP2,const int& ii) const {
const int ncount = d_ncount(ii);
// if not nnn neighbors, order parameter = 0
if ((ncount == 0) || (ncount < nnn))
return;
calc_boop2(ncount, ii);
}

View File

@ -38,7 +38,20 @@ ModifyKokkos::ModifyKokkos(LAMMPS *lmp) : Modify(lmp)
void ModifyKokkos::setup(int vflag)
{
// compute setup needs to come before fix setup
// b/c NH fixes need use DOF of temperature computes
// b/c NH fixes need DOF of temperature computes
// fix group setup() is special case since populates a dynamic group
// needs to be done before temperature compute setup
for (int i = 0; i < nfix; i++) {
if (strcmp(fix[i]->style,"GROUP") == 0) {
atomKK->sync(fix[i]->execution_space,fix[i]->datamask_read);
int prev_auto_sync = lmp->kokkos->auto_sync;
if (!fix[i]->kokkosable) lmp->kokkos->auto_sync = 1;
fix[i]->setup(vflag);
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(fix[i]->execution_space,fix[i]->datamask_modify);
}
}
for (int i = 0; i < ncompute; i++) compute[i]->setup();
@ -124,6 +137,37 @@ void ModifyKokkos::setup_pre_neighbor()
}
}
/* ----------------------------------------------------------------------
setup post_neighbor call, only for fixes that define post_neighbor
called from Verlet, RESPA
------------------------------------------------------------------------- */
void ModifyKokkos::setup_post_neighbor()
{
if (update->whichflag == 1)
for (int i = 0; i < n_post_neighbor; i++) {
atomKK->sync(fix[list_post_neighbor[i]]->execution_space,
fix[list_post_neighbor[i]]->datamask_read);
int prev_auto_sync = lmp->kokkos->auto_sync;
if (!fix[list_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1;
fix[list_post_neighbor[i]]->setup_post_neighbor();
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(fix[list_post_neighbor[i]]->execution_space,
fix[list_post_neighbor[i]]->datamask_modify);
}
else if (update->whichflag == 2)
for (int i = 0; i < n_min_post_neighbor; i++) {
atomKK->sync(fix[list_min_post_neighbor[i]]->execution_space,
fix[list_min_post_neighbor[i]]->datamask_read);
int prev_auto_sync = lmp->kokkos->auto_sync;
if (!fix[list_min_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1;
fix[list_min_post_neighbor[i]]->setup_post_neighbor();
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(fix[list_min_post_neighbor[i]]->execution_space,
fix[list_min_post_neighbor[i]]->datamask_modify);
}
}
/* ----------------------------------------------------------------------
setup pre_force call, only for fixes that define pre_force
called from Verlet, RESPA, Min
@ -258,6 +302,24 @@ void ModifyKokkos::pre_neighbor()
}
}
/* ----------------------------------------------------------------------
post_neighbor call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyKokkos::post_neighbor()
{
for (int i = 0; i < n_post_neighbor; i++) {
atomKK->sync(fix[list_post_neighbor[i]]->execution_space,
fix[list_post_neighbor[i]]->datamask_read);
int prev_auto_sync = lmp->kokkos->auto_sync;
if (!fix[list_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1;
fix[list_post_neighbor[i]]->post_neighbor();
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(fix[list_post_neighbor[i]]->execution_space,
fix[list_post_neighbor[i]]->datamask_modify);
}
}
/* ----------------------------------------------------------------------
pre_force call, only for relevant fixes
------------------------------------------------------------------------- */
@ -420,6 +482,12 @@ void ModifyKokkos::post_run()
atomKK->modified(fix[i]->execution_space,
fix[i]->datamask_modify);
}
// must reset this to its default value, since computes may be added
// or removed between runs and with this change we will redirect any
// calls to addstep_compute() to addstep_compute_all() instead.
n_timeflag = -1;
}
/* ----------------------------------------------------------------------
@ -567,6 +635,24 @@ void ModifyKokkos::min_pre_neighbor()
}
}
/* ----------------------------------------------------------------------
minimizer post-neighbor call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyKokkos::min_post_neighbor()
{
for (int i = 0; i < n_min_post_neighbor; i++) {
atomKK->sync(fix[list_min_post_neighbor[i]]->execution_space,
fix[list_min_post_neighbor[i]]->datamask_read);
int prev_auto_sync = lmp->kokkos->auto_sync;
if (!fix[list_min_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1;
fix[list_min_post_neighbor[i]]->min_post_neighbor();
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(fix[list_min_post_neighbor[i]]->execution_space,
fix[list_min_post_neighbor[i]]->datamask_modify);
}
}
/* ----------------------------------------------------------------------
minimizer pre-force call, only for relevant fixes
------------------------------------------------------------------------- */
@ -646,7 +732,7 @@ double ModifyKokkos::min_energy(double *fextra)
}
/* ----------------------------------------------------------------------
store current state of extra dof, only for relevant fixes
store current state of extra minimizer dof, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyKokkos::min_store()
@ -664,7 +750,7 @@ void ModifyKokkos::min_store()
}
/* ----------------------------------------------------------------------
mange state of extra dof on a stack, only for relevant fixes
manage state of extra minimizer dof on a stack, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyKokkos::min_clearstore()
@ -710,7 +796,7 @@ void ModifyKokkos::min_popstore()
}
/* ----------------------------------------------------------------------
displace extra dof along vector hextra, only for relevant fixes
displace extra minimizer dof along vector hextra, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyKokkos::min_step(double alpha, double *hextra)
@ -755,7 +841,7 @@ double ModifyKokkos::max_alpha(double *hextra)
}
/* ----------------------------------------------------------------------
extract extra dof for minimization, only for relevant fixes
extract extra minimizer dof, only for relevant fixes
------------------------------------------------------------------------- */
int ModifyKokkos::min_dof()
@ -775,7 +861,7 @@ int ModifyKokkos::min_dof()
}
/* ----------------------------------------------------------------------
reset reference state of fix, only for relevant fixes
reset minimizer reference state of fix, only for relevant fixes
------------------------------------------------------------------------- */
int ModifyKokkos::min_reset_ref()
@ -788,8 +874,8 @@ int ModifyKokkos::min_reset_ref()
int prev_auto_sync = lmp->kokkos->auto_sync;
if (!fix[list_min_energy[i]]->kokkosable) lmp->kokkos->auto_sync = 1;
itmp = fix[list_min_energy[i]]->min_reset_ref();
lmp->kokkos->auto_sync = prev_auto_sync;
if (itmp) itmpall = 1;
lmp->kokkos->auto_sync = prev_auto_sync;
atomKK->modified(fix[list_min_energy[i]]->execution_space,
fix[list_min_energy[i]]->datamask_modify);
}

View File

@ -26,6 +26,7 @@ class ModifyKokkos : public Modify {
void setup(int);
void setup_pre_exchange();
void setup_pre_neighbor();
void setup_post_neighbor();
void setup_pre_force(int);
void setup_pre_reverse(int, int);
void initial_integrate(int);
@ -33,6 +34,7 @@ class ModifyKokkos : public Modify {
void pre_decide();
void pre_exchange();
void pre_neighbor();
void post_neighbor();
void pre_force(int);
void pre_reverse(int,int);
void post_force(int);
@ -52,6 +54,7 @@ class ModifyKokkos : public Modify {
void min_pre_exchange();
void min_pre_neighbor();
void min_post_neighbor();
void min_pre_force(int);
void min_pre_reverse(int,int);
void min_post_force(int);

View File

@ -29,6 +29,8 @@ namespace LAMMPS_NS {
template<class DeviceType, int HALF_NEIGH, int GHOST, int TRI, int SIZE>
NPairKokkos<DeviceType,HALF_NEIGH,GHOST,TRI,SIZE>::NPairKokkos(LAMMPS *lmp) : NPair(lmp) {
last_stencil_old = -1;
// use 1D view for scalars to reduce GPU memory operations
d_scalars = typename AT::t_int_1d("neighbor:scalars",2);
@ -112,9 +114,11 @@ void NPairKokkos<DeviceType,HALF_NEIGH,GHOST,TRI,SIZE>::copy_stencil_info()
NPair::copy_stencil_info();
nstencil = ns->nstencil;
if (ns->last_stencil == update->ntimestep) {
if (ns->last_stencil != last_stencil_old) {
// copy stencil to device as it may have changed
last_stencil_old = ns->last_stencil;
int maxstencil = ns->get_maxstencil();
if (maxstencil > (int)k_stencil.extent(0))

View File

@ -138,7 +138,7 @@ class NPairKokkos : public NPair {
// data from NStencil class
int nstencil;
int nstencil,last_stencil_old;
DAT::tdual_int_1d k_stencil; // # of J neighs for each I
DAT::tdual_int_1d_3 k_stencilxyz;
};

View File

@ -31,6 +31,7 @@
#include "domain.h"
#include "error.h"
#include "fix.h"
#include "fix_store.h"
#include "force.h"
#include "group.h"
#include "input.h"
@ -87,9 +88,9 @@ enum{X,Y,Z, // required for vtk, must come first
Q,MUX,MUY,MUZ,MU,RADIUS,DIAMETER,
OMEGAX,OMEGAY,OMEGAZ,ANGMOMX,ANGMOMY,ANGMOMZ,
TQX,TQY,TQZ,
VARIABLE,COMPUTE,FIX,INAME,DNAME,
COMPUTE,FIX,VARIABLE,IVEC,DVEC,IARRAY,DARRAY,
ATTRIBUTES}; // must come last
enum{LT,LE,GT,GE,EQ,NEQ};
enum{LT,LE,GT,GE,EQ,NEQ,XOR};
enum{VTK,VTP,VTU,PVTP,PVTU}; // file formats
#define ONEFIELD 32
@ -119,11 +120,10 @@ DumpVTK::DumpVTK(LAMMPS *lmp, int narg, char **arg) :
// ioptional = start of additional optional args
// only dump image and dump movie styles process optional args
ioptional = parse_fields(narg,arg);
ioptional = parse_fields(nargnew,earg);
if (ioptional < narg &&
strcmp(style,"image") != 0 && strcmp(style,"movie") != 0)
error->all(FLERR,"Invalid attribute in dump vtk command");
if (ioptional < nargnew)
error->all(FLERR,"Invalid attribute {} in dump vtk command", earg[ioptional]);
size_one = pack_choice.size();
current_pack_choice_key = -1;
@ -210,38 +210,40 @@ void DumpVTK::init_style()
else
write_choice = &DumpVTK::write_vtk;
// find current ptr for each compute,fix,variable
// find current ptr for each compute,fix,variable and custom atom property
// check that fix frequency is acceptable
int icompute;
for (int i = 0; i < ncompute; i++) {
icompute = modify->find_compute(id_compute[i]);
int icompute = modify->find_compute(id_compute[i]);
if (icompute < 0) error->all(FLERR,"Could not find dump vtk compute ID");
compute[i] = modify->compute[icompute];
}
int ifix;
for (int i = 0; i < nfix; i++) {
ifix = modify->find_fix(id_fix[i]);
int ifix = modify->find_fix(id_fix[i]);
if (ifix < 0) error->all(FLERR,"Could not find dump vtk fix ID");
fix[i] = modify->fix[ifix];
if (nevery % modify->fix[ifix]->peratom_freq)
error->all(FLERR,"Dump vtk and fix not computed at compatible times");
}
int ivariable;
for (int i = 0; i < nvariable; i++) {
ivariable = input->variable->find(id_variable[i]);
int ivariable = input->variable->find(id_variable[i]);
if (ivariable < 0)
error->all(FLERR,"Could not find dump vtk variable name");
variable[i] = ivariable;
}
int icustom;
int icustom,flag,cols;
for (int i = 0; i < ncustom; i++) {
icustom = atom->find_custom(id_custom[i],flag_custom[i]);
icustom = atom->find_custom(id_custom[i],flag,cols);
if (icustom < 0)
error->all(FLERR,"Could not find custom per-atom property ID");
custom[i] = icustom;
if (!flag && !cols) custom_flag[i] = IVEC;
else if (flag && !cols) custom_flag[i] = DVEC;
else if (!flag && cols) custom_flag[i] = IARRAY;
else if (flag && cols) custom_flag[i] = DARRAY;
}
// set index and check validity of region
@ -275,7 +277,7 @@ int DumpVTK::count()
// grow choose and variable vbuf arrays if needed
int nlocal = atom->nlocal;
const int nlocal = atom->nlocal;
if (atom->nmax > maxlocal) {
maxlocal = atom->nmax;
@ -345,10 +347,10 @@ int DumpVTK::count()
// un-choose if any threshold criterion isn't met
if (nthresh) {
double *ptr;
double *ptr,*ptrhold;
double *values;
double value;
int nstride;
int nlocal = atom->nlocal;
int nstride,lastflag;
for (int ithresh = 0; ithresh < nthresh; ithresh++) {
@ -635,26 +637,22 @@ int DumpVTK::count()
nstride = 1;
} else if (thresh_array[ithresh] == MUX) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][0];
nstride = 4;
} else if (thresh_array[ithresh] == MUY) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][1];
nstride = 4;
} else if (thresh_array[ithresh] == MUZ) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][2];
nstride = 4;
} else if (thresh_array[ithresh] == MU) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][3];
nstride = 4;
@ -753,9 +751,8 @@ int DumpVTK::count()
nstride = 1;
} else if (thresh_array[ithresh] == IVEC) {
int iwhich,flag,cols
i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols);
int iwhich = custom[field2index[i]];
int *ivector = atom->ivector[iwhich];
for (i = 0; i < nlocal; i++)
dchoose[i] = ivector[i];
@ -763,16 +760,14 @@ int DumpVTK::count()
nstride = 1;
} else if (thresh_array[ithresh] == DVEC) {
int iwhich,flag,cols;
i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols);
int iwhich = custom[field2index[i]];
ptr = atom->dvector[iwhich];
nstride = 1;
} else if (thresh_array[ithresh] == IARRAY) {
int iwhich,flag,cols;
i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols);
int iwhich = custom[field2index[i]];
int **iarray = atom->iarray[iwhich];
int icol = argindex[i] - 1;
for (i = 0; i < nlocal; i++)
@ -781,43 +776,99 @@ int DumpVTK::count()
nstride = 1;
} else if (thresh_array[ithresh] == DARRAY) {
int iwhich,flag,cols;
i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols)
int iwhich = custom[field2index[i]];
double **darray = atom->darray[iwhich];
ptr = &darray[0][argindex[i]-1];
nstride = atom->dcols[iwhich];
}
// unselect atoms that don't meet threshold criterion
// compare to single value or values stored in threshfix
// copy ptr attribute into thresh_fix if this is first comparison
value = thresh_value[ithresh];
if (thresh_last[ithresh] < 0) {
lastflag = 0;
value = thresh_value[ithresh];
} else {
lastflag = 1;
int ilast = thresh_last[ithresh];
values = thresh_fix[ilast]->vstore;
ptrhold = ptr;
if (thresh_first[ilast]) {
thresh_first[ilast] = 0;
for (i = 0; i < nlocal; i++, ptr += nstride) values[i] = *ptr;
ptr = ptrhold;
}
}
switch (thresh_op[ithresh]) {
case LT:
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr >= value) choose[i] = 0;
break;
case LE:
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr > value) choose[i] = 0;
break;
case GT:
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr <= value) choose[i] = 0;
break;
case GE:
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr < value) choose[i] = 0;
break;
case EQ:
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != value) choose[i] = 0;
break;
case NEQ:
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr == value) choose[i] = 0;
break;
if (thresh_op[ithresh] == LT) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr >= values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr >= value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == LE) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr > values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr > value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == GT) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr <= values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr <= value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == GE) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr < values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr < value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == EQ) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == NEQ) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr == values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr == value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == XOR) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if ((choose[i] && *ptr == 0.0 && values[i] == 0.0) ||
(*ptr != 0.0 && values[i] != 0.0))
choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if ((choose[i] && *ptr == 0.0 && value == 0.0) ||
(*ptr != 0.0 && value != 0.0))
choose[i] = 0;
}
}
// update values stored in threshfix
if (lastflag) {
ptr = ptrhold;
for (i = 0; i < nlocal; i++, ptr += nstride) values[i] = *ptr;
}
}
}
@ -1754,15 +1805,16 @@ int DumpVTK::parse_fields(int narg, char **arg)
} else {
int n,tmp;
int n,flag,cols;
ArgInfo argi(arg[iarg],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE
|ArgInfo::DVEC|ArgInfo::IVEC);
|ArgInfo::DNAME|ArgInfo::INAME);
argindex[ATTRIBUTES+i] = argi.get_index1();
auto aname = argi.get_name();
switch (argi.get_type()) {
case ArgInfo::UNKNOWN:
error->all(FLERR,"Invalid attribute in dump vtk command");
error->all(FLERR,"Invalid attribute in dump vtk command: {}",arg[iarg]);
break;
// compute value = c_ID
@ -1772,21 +1824,19 @@ int DumpVTK::parse_fields(int narg, char **arg)
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_compute;
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
n = modify->find_compute(argi.get_name());
if (n < 0) error->all(FLERR,"Could not find dump vtk compute ID");
n = modify->find_compute(aname);
if (n < 0) error->all(FLERR,"Could not find dump vtk compute ID: {}",aname);
if (modify->compute[n]->peratom_flag == 0)
error->all(FLERR,"Dump vtk compute does not compute per-atom info");
error->all(FLERR,"Dump vtk compute {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0)
error->all(FLERR,
"Dump vtk compute does not calculate per-atom vector");
error->all(FLERR,"Dump vtk compute {} does not calculate per-atom vector",aname);
if (argi.get_dim() > 0 && modify->compute[n]->size_peratom_cols == 0)
error->all(FLERR,
"Dump vtk compute does not calculate per-atom array");
error->all(FLERR,"Dump vtk compute {} does not calculate per-atom array",aname);
if (argi.get_dim() > 0 &&
argi.get_index1() > modify->compute[n]->size_peratom_cols)
error->all(FLERR,"Dump vtk compute vector is accessed out-of-range");
error->all(FLERR,"Dump vtk compute {} vector is accessed out-of-range",aname);
field2index[ATTRIBUTES+i] = add_compute(argi.get_name());
field2index[ATTRIBUTES+i] = add_compute(aname);
name[ATTRIBUTES+i] = arg[iarg];
break;
@ -1797,19 +1847,19 @@ int DumpVTK::parse_fields(int narg, char **arg)
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_fix;
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
n = modify->find_fix(argi.get_name());
if (n < 0) error->all(FLERR,"Could not find dump vtk fix ID");
n = modify->find_fix(aname);
if (n < 0) error->all(FLERR,"Could not find dump vtk fix ID: {}",aname);
if (modify->fix[n]->peratom_flag == 0)
error->all(FLERR,"Dump vtk fix does not compute per-atom info");
error->all(FLERR,"Dump vtk fix {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0)
error->all(FLERR,"Dump vtk fix does not compute per-atom vector");
error->all(FLERR,"Dump vtk fix {} does not compute per-atom vector",aname);
if (argi.get_dim() > 0 && modify->fix[n]->size_peratom_cols == 0)
error->all(FLERR,"Dump vtk fix does not compute per-atom array");
error->all(FLERR,"Dump vtk fix {} does not compute per-atom array",aname);
if (argi.get_dim() > 0 &&
argi.get_index1() > modify->fix[n]->size_peratom_cols)
error->all(FLERR,"Dump vtk fix vector is accessed out-of-range");
error->all(FLERR,"Dump vtk fix {} vector is accessed out-of-range",aname);
field2index[ATTRIBUTES+i] = add_fix(argi.get_name());
field2index[ATTRIBUTES+i] = add_fix(aname);
name[ATTRIBUTES+i] = arg[iarg];
break;
@ -1819,61 +1869,62 @@ int DumpVTK::parse_fields(int narg, char **arg)
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_variable;
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
n = input->variable->find(argi.get_name());
if (n < 0) error->all(FLERR,"Could not find dump vtk variable name");
n = input->variable->find(aname);
if (n < 0) error->all(FLERR,"Could not find dump vtk variable name {}",aname);
if (input->variable->atomstyle(n) == 0)
error->all(FLERR,"Dump vtk variable is not atom-style variable");
error->all(FLERR,"Dump vtk variable {} is not atom-style variable",aname);
field2index[ATTRIBUTES+i] = add_variable(argi.get_name());
field2index[ATTRIBUTES+i] = add_variable(aname);
name[ATTRIBUTES+i] = arg[iarg];
break;
// custom per-atom integer vector = i_ID
case ArgInfo::INAME:
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
vtype[ATTRIBUTES+i] = Dump::INT;
tmp = -1;
n = atom->find_custom(argi.get_name(),tmp);
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID");
if (tmp != 0)
error->all(FLERR,"Custom per-atom property ID is not integer");
field2index[ATTRIBUTES+i] = add_custom(argi.get_name(),0);
name[ATTRIBUTES+i] = arg[iarg];
break;
// custom per-atom floating point vector = d_ID
// custom per-atom floating point vector or array = d_ID d2_ID
case ArgInfo::DNAME:
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
vtype[ATTRIBUTES+i] = Dump::DOUBLE;
tmp = -1;
n = atom->find_custom(argi.get_name(),tmp);
n = atom->find_custom(aname,flag,cols);
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID");
if (tmp != 1)
error->all(FLERR,"Custom per-atom property ID is not floating point");
field2index[ATTRIBUTES+i] = add_custom(argi.get_name(),1);
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+i] == 0) {
if (!flag || cols)
error->all(FLERR,"Property double vector {} for dump vtk does not exist",aname);
} else {
if (!flag || !cols)
error->all(FLERR,"Property double array {} for dump vtk does not exist",aname);
if (argindex[ATTRIBUTES+i] > atom->dcols[n])
error->all(FLERR,"Dump vtk property array {} is accessed out-of-range",aname);
}
field2index[ATTRIBUTES+i] = add_custom(aname,1);
name[ATTRIBUTES+i] = arg[iarg];
break;
// NEWSTYLE
// custom per-atom integer array = i2_ID
// custom per-atom integer vector or array = i_ID or i2_ID
case ArgInfo::IARRAY:
return iarg;
case ArgInfo::INAME:
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
vtype[ATTRIBUTES+i] = Dump::INT;
// custom per-atom floating point array = d2_ID
n = atom->find_custom(aname,flag,cols);
case ArgInfo::DARRAY:
return iarg;
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+i] == 0) {
if (flag || cols)
error->all(FLERR,"Property integer vector {} for dump vtk does not exist",aname);
} else {
if (flag || !cols)
error->all(FLERR,"Property integer array {} for dump vtk does not exist",aname);
if (argindex[ATTRIBUTES+i] > atom->icols[n])
error->all(FLERR,"Dump vtk property array {} is accessed out-of-range",aname);
}
field2index[ATTRIBUTES+i] = add_custom(aname,0);
name[ATTRIBUTES+i] = arg[iarg];
break;
// no match
default:
return iarg;
@ -1948,12 +1999,10 @@ int DumpVTK::add_compute(const char *id)
id_compute = (char **)
memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute");
delete [] compute;
delete[] compute;
compute = new Compute*[ncompute+1];
int n = strlen(id) + 1;
id_compute[ncompute] = new char[n];
strcpy(id_compute[ncompute],id);
id_compute[ncompute] = utils::strdup(id);
ncompute++;
return ncompute-1;
}
@ -1973,12 +2022,10 @@ int DumpVTK::add_fix(const char *id)
id_fix = (char **)
memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix");
delete [] fix;
delete[] fix;
fix = new Fix*[nfix+1];
int n = strlen(id) + 1;
id_fix[nfix] = new char[n];
strcpy(id_fix[nfix],id);
id_fix[nfix] = utils::strdup(id);
nfix++;
return nfix-1;
}
@ -1999,22 +2046,20 @@ int DumpVTK::add_variable(const char *id)
id_variable = (char **)
memory->srealloc(id_variable,(nvariable+1)*sizeof(char *),
"dump:id_variable");
delete [] variable;
delete[] variable;
variable = new int[nvariable+1];
delete [] vbuf;
delete[] vbuf;
vbuf = new double*[nvariable+1];
for (int i = 0; i <= nvariable; i++) vbuf[i] = nullptr;
int n = strlen(id) + 1;
id_variable[nvariable] = new char[n];
strcpy(id_variable[nvariable],id);
id_variable[nvariable] = utils::strdup(id);
nvariable++;
return nvariable-1;
}
/* ----------------------------------------------------------------------
add custom atom property to list used by dump
return index of where this property is in list
return index of where this property is in Atom class custom lists
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
@ -2022,21 +2067,17 @@ int DumpVTK::add_custom(const char *id, int flag)
{
int icustom;
for (icustom = 0; icustom < ncustom; icustom++)
if ((strcmp(id,id_custom[icustom]) == 0)
&& (flag == flag_custom[icustom])) break;
if (strcmp(id,id_custom[icustom]) == 0) break;
if (icustom < ncustom) return icustom;
id_custom = (char **)
memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom");
flag_custom = (int *)
memory->srealloc(flag_custom,(ncustom+1)*sizeof(int),"dump:flag_custom");
int n = strlen(id) + 1;
id_custom[ncustom] = new char[n];
strcpy(id_custom[ncustom],id);
flag_custom[ncustom] = flag;
id_custom = (char **) memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom");
custom = (int *) memory->srealloc(custom,(ncustom+1)*sizeof(int),"dump:custom");
custom_flag = (int *) memory->srealloc(custom_flag,(ncustom+1)*sizeof(int),"dump:custom_flag");
id_custom[ncustom] = utils::strdup(id);
custom_flag[ncustom] = flag;
ncustom++;
return ncustom-1;
}
@ -2050,21 +2091,17 @@ int DumpVTK::modify_param(int narg, char **arg)
else {
iregion = domain->find_region(arg[1]);
if (iregion == -1)
error->all(FLERR,"Dump_modify region ID does not exist");
delete [] idregion;
int n = strlen(arg[1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[1]);
error->all(FLERR,"Dump_modify region ID {} does not exist",arg[1]);
delete[] idregion;
idregion = utils::strdup(arg[1]);
}
return 2;
}
if (strcmp(arg[0],"label") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command [label]");
delete [] label;
int n = strlen(arg[1]) + 1;
label = new char[n];
strcpy(label,arg[1]);
delete[] label;
label = utils::strdup(arg[1]);
return 2;
}
@ -2078,23 +2115,29 @@ int DumpVTK::modify_param(int narg, char **arg)
if (strcmp(arg[0],"element") == 0) {
if (narg < ntypes+1)
error->all(FLERR,"Dump modify: number of element names do not match atom types");
if (typenames) {
for (int i = 1; i <= ntypes; i++) delete [] typenames[i];
delete [] typenames;
typenames = nullptr;
}
error->all(FLERR,"Number of dump_modify element names does not match number of atom types");
for (int i = 1; i <= ntypes; i++) delete[] typenames[i];
delete[] typenames;
typenames = new char*[ntypes+1];
for (int itype = 1; itype <= ntypes; itype++) {
int n = strlen(arg[itype]) + 1;
typenames[itype] = new char[n];
strcpy(typenames[itype],arg[itype]);
typenames[itype] = utils::strdup(arg[itype]);
}
return ntypes+1;
}
if (strcmp(arg[0],"refresh") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
ArgInfo argi(arg[1],ArgInfo::COMPUTE);
if ((argi.get_type() != ArgInfo::COMPUTE) || (argi.get_dim() != 0))
error->all(FLERR,"Illegal dump_modify command");
if (refreshflag) error->all(FLERR,"Dump_modify can only have one refresh");
refreshflag = 1;
refresh = argi.copy_name();
return 2;
}
if (strcmp(arg[0],"thresh") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"none") == 0) {
@ -2105,8 +2148,16 @@ int DumpVTK::modify_param(int narg, char **arg)
thresh_array = nullptr;
thresh_op = nullptr;
thresh_value = nullptr;
thresh_last = nullptr;
for (int i = 0; i < nthreshlast; i++) {
modify->delete_fix(thresh_fixID[i]);
delete[] thresh_fixID[i];
}
thresh_fix = nullptr;
thresh_fixID = nullptr;
thresh_first = nullptr;
}
nthresh = 0;
nthresh = nthreshlast = 0;
return 2;
}
@ -2117,6 +2168,7 @@ int DumpVTK::modify_param(int narg, char **arg)
memory->grow(thresh_array,nthresh+1,"dump:thresh_array");
memory->grow(thresh_op,(nthresh+1),"dump:thresh_op");
memory->grow(thresh_value,(nthresh+1),"dump:thresh_value");
memory->grow(thresh_last,(nthresh+1),"dump:thresh_last");
// set attribute type of threshold
// customize by adding to if statement
@ -2199,98 +2251,125 @@ int DumpVTK::modify_param(int narg, char **arg)
else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY;
else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ;
// compute value = c_ID
// if no trailing [], then arg is set to 0, else arg is between []
// compute or fix or variable or custom vector/array
else if (strncmp(arg[1],"c_",2) == 0) {
thresh_array[nthresh] = COMPUTE;
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
else {
int n,flag,cols;
ArgInfo argi(arg[1],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE
|ArgInfo::DNAME|ArgInfo::INAME);
argindex[ATTRIBUTES+nfield+nthresh] = argi.get_index1();
auto aname = argi.get_name();
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Invalid attribute in dump modify command");
argindex[ATTRIBUTES+nfield+nthresh] = atoi(ptr+1);
*ptr = '\0';
} else argindex[ATTRIBUTES+nfield+nthresh] = 0;
switch (argi.get_type()) {
n = modify->find_compute(suffix);
if (n < 0) error->all(FLERR,"Could not find dump modify compute ID");
case ArgInfo::UNKNOWN:
error->all(FLERR,"Invalid attribute in dump modify command");
break;
if (modify->compute[n]->peratom_flag == 0)
error->all(FLERR,
"Dump modify compute ID does not compute per-atom info");
if (argindex[ATTRIBUTES+nfield+nthresh] == 0 &&
modify->compute[n]->size_peratom_cols > 0)
error->all(FLERR,
"Dump modify compute ID does not compute per-atom vector");
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
modify->compute[n]->size_peratom_cols == 0)
error->all(FLERR,
"Dump modify compute ID does not compute per-atom array");
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
argindex[ATTRIBUTES+nfield+nthresh] > modify->compute[n]->size_peratom_cols)
error->all(FLERR,"Dump modify compute ID vector is not large enough");
// compute value = c_ID
// if no trailing [], then arg is set to 0, else arg is between []
field2index[ATTRIBUTES+nfield+nthresh] = add_compute(suffix);
delete [] suffix;
case ArgInfo::COMPUTE:
thresh_array[nthresh] = COMPUTE;
n = modify->find_compute(aname);
if (n < 0) error->all(FLERR,"Could not find dump modify compute ID: {}",aname);
// fix value = f_ID
// if no trailing [], then arg is set to 0, else arg is between []
if (modify->compute[n]->peratom_flag == 0)
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0)
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom vector",aname);
if (argi.get_index1() > 0 && modify->compute[n]->size_peratom_cols == 0)
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom array",aname);
if (argi.get_index1() > 0 &&
argi.get_index1() > modify->compute[n]->size_peratom_cols)
error->all(FLERR,"Dump modify compute ID {} vector is not large enough",aname);
} else if (strncmp(arg[1],"f_",2) == 0) {
thresh_array[nthresh] = FIX;
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
field2index[ATTRIBUTES+nfield+nthresh] = add_compute(aname);
break;
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Invalid attribute in dump modify command");
argindex[ATTRIBUTES+nfield+nthresh] = atoi(ptr+1);
*ptr = '\0';
} else argindex[ATTRIBUTES+nfield+nthresh] = 0;
// fix value = f_ID
// if no trailing [], then arg is set to 0, else arg is between []
n = modify->find_fix(suffix);
if (n < 0) error->all(FLERR,"Could not find dump modify fix ID");
case ArgInfo::FIX:
thresh_array[nthresh] = FIX;
n = modify->find_fix(aname);
if (n < 0) error->all(FLERR,"Could not find dump modify fix ID: {}",aname);
if (modify->fix[n]->peratom_flag == 0)
error->all(FLERR,"Dump modify fix ID does not compute per-atom info");
if (argindex[ATTRIBUTES+nfield+nthresh] == 0 &&
modify->fix[n]->size_peratom_cols > 0)
error->all(FLERR,"Dump modify fix ID does not compute per-atom vector");
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
modify->fix[n]->size_peratom_cols == 0)
error->all(FLERR,"Dump modify fix ID does not compute per-atom array");
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
argindex[ATTRIBUTES+nfield+nthresh] > modify->fix[n]->size_peratom_cols)
error->all(FLERR,"Dump modify fix ID vector is not large enough");
if (modify->fix[n]->peratom_flag == 0)
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0)
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom vector",aname);
if (argi.get_index1() > 0 && modify->fix[n]->size_peratom_cols == 0)
error->all(FLERR,"Dump modify fix ID {} does not compute per-atom array",aname);
if (argi.get_index1() > 0 && argi.get_index1() > modify->fix[n]->size_peratom_cols)
error->all(FLERR,"Dump modify fix ID {} vector is not large enough",aname);
field2index[ATTRIBUTES+nfield+nthresh] = add_fix(suffix);
delete [] suffix;
field2index[ATTRIBUTES+nfield+nthresh] = add_fix(aname);
break;
// variable value = v_ID
// variable value = v_ID
} else if (strncmp(arg[1],"v_",2) == 0) {
thresh_array[nthresh] = VARIABLE;
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
case ArgInfo::VARIABLE:
thresh_array[nthresh] = VARIABLE;
n = input->variable->find(aname);
if (n < 0) error->all(FLERR,"Could not find dump modify variable name: {}",aname);
if (input->variable->atomstyle(n) == 0)
error->all(FLERR,"Dump modify variable {} is not atom-style variable",aname);
argindex[ATTRIBUTES+nfield+nthresh] = 0;
field2index[ATTRIBUTES+nfield+nthresh] = add_variable(aname);
break;
n = input->variable->find(suffix);
if (n < 0) error->all(FLERR,"Could not find dump modify variable name");
if (input->variable->atomstyle(n) == 0)
error->all(FLERR,"Dump modify variable is not atom-style variable");
// custom per atom floating point vector or array
field2index[ATTRIBUTES+nfield+nthresh] = add_variable(suffix);
delete [] suffix;
case ArgInfo::DNAME:
n = atom->find_custom(aname,flag,cols);
} else error->all(FLERR,"Invalid dump_modify threshold operator");
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+nfield+nthresh] == 0) {
if (!flag || cols)
error->all(FLERR,"Property double vector for dump custom does not exist");
thresh_array[nthresh] = DVEC;
} else {
if (!flag || !cols)
error->all(FLERR,"Property double array for dump custom does not exist");
if (argindex[ATTRIBUTES+nfield+nthresh] > atom->dcols[n])
error->all(FLERR,"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = DARRAY;
}
field2index[ATTRIBUTES+nfield+nthresh] = add_custom(aname,thresh_array[nthresh]);
break;
// custom per atom integer vector or array
case ArgInfo::INAME:
n = atom->find_custom(aname,flag,cols);
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+nfield+nthresh] == 0) {
if (flag || cols)
error->all(FLERR,"Property integer vector for dump custom does not exist");
thresh_array[nthresh] = IVEC;
} else {
if (flag || !cols)
error->all(FLERR,"Property integer array for dump custom does not exist");
if (argindex[ATTRIBUTES+nfield+nthresh] > atom->icols[n])
error->all(FLERR,"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = IARRAY;
}
field2index[ATTRIBUTES+nfield+nthresh] = add_custom(aname,thresh_array[nthresh]);
break;
// no match
default:
error->all(FLERR,"Invalid dump_modify thresh attribute: {}",aname);
break;
}
}
// set operation type of threshold
@ -2300,11 +2379,32 @@ int DumpVTK::modify_param(int narg, char **arg)
else if (strcmp(arg[2],">=") == 0) thresh_op[nthresh] = GE;
else if (strcmp(arg[2],"==") == 0) thresh_op[nthresh] = EQ;
else if (strcmp(arg[2],"!=") == 0) thresh_op[nthresh] = NEQ;
else error->all(FLERR,"Invalid dump_modify threshold operator");
else if (strcmp(arg[2],"|^") == 0) thresh_op[nthresh] = XOR;
else error->all(FLERR,"Invalid dump_modify thresh operator");
// set threshold value
// set threshold value as number or special LAST keyword
// create FixStore to hold LAST values, should work with restart
// id = dump-ID + nthreshlast + DUMP_STORE, fix group = dump group
thresh_value[nthresh] = utils::numeric(FLERR,arg[3],false,lmp);
if (strcmp(arg[3],"LAST") != 0) {
thresh_value[nthresh] = utils::numeric(FLERR,arg[3],false,lmp);
thresh_last[nthresh] = -1;
} else {
thresh_fix = (FixStore **)
memory->srealloc(thresh_fix,(nthreshlast+1)*sizeof(FixStore *),"dump:thresh_fix");
thresh_fixID = (char **)
memory->srealloc(thresh_fixID,(nthreshlast+1)*sizeof(char *),"dump:thresh_fixID");
memory->grow(thresh_first,(nthreshlast+1),"dump:thresh_first");
std::string threshid = fmt::format("{}{}_DUMP_STORE",id,nthreshlast);
thresh_fixID[nthreshlast] = utils::strdup(threshid);
threshid += fmt::format(" {} STORE peratom 1 1", group->names[igroup]);
thresh_fix[nthreshlast] = (FixStore *) modify->add_fix(threshid);
thresh_last[nthreshlast] = nthreshlast;
thresh_first[nthreshlast] = 1;
nthreshlast++;
}
nthresh++;
return 4;
@ -2389,25 +2489,35 @@ void DumpVTK::pack_variable(int n)
void DumpVTK::pack_custom(int n)
{
int index = field2index[n];
if (flag_custom[index] == 0) { // integer
int iwhich,tmp;
iwhich = atom->find_custom(id_custom[index],tmp);
int flag = custom_flag[field2index[current_pack_choice_key]];
int iwhich = custom[field2index[current_pack_choice_key]];
int index = argindex[current_pack_choice_key];
if (flag == IVEC) {
int *ivector = atom->ivector[iwhich];
for (int i = 0; i < nchoose; i++) {
buf[n] = ivector[clist[i]];
n += size_one;
}
} else if (flag_custom[index] == 1) { // double
int iwhich,tmp;
iwhich = atom->find_custom(id_custom[index],tmp);
} else if (flag == DVEC) {
double *dvector = atom->dvector[iwhich];
for (int i = 0; i < nchoose; i++) {
buf[n] = dvector[clist[i]];
n += size_one;
}
} else if (flag == IARRAY) {
index--;
int **iarray = atom->iarray[iwhich];
for (int i = 0; i < nchoose; i++) {
buf[n] = iarray[clist[i]][index];
n += size_one;
}
} else if (flag == DARRAY) {
index--;
double **darray = atom->darray[iwhich];
for (int i = 0; i < nchoose; i++) {
buf[n] = darray[clist[i]][index];
n += size_one;
}
}
}

View File

@ -198,6 +198,8 @@ void ComputeOrientOrderAtom::init()
error->all(FLERR,"Compute orientorder/atom cutoff is "
"longer than pairwise cutoff");
memory->destroy(qnm_r);
memory->destroy(qnm_i);
memory->create(qnm_r,nqlist,2*qmax+1,"orientorder/atom:qnm_r");
memory->create(qnm_i,nqlist,2*qmax+1,"orientorder/atom:qnm_i");
@ -669,6 +671,7 @@ void ComputeOrientOrderAtom::init_clebsch_gordan()
idxcg_count++;
}
idxcg_max = idxcg_count;
memory->destroy(cglist);
memory->create(cglist, idxcg_max, "computeorientorderatom:cglist");
idxcg_count = 0;

View File

@ -131,7 +131,7 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
if (ioptional < nfield &&
strcmp(style,"image") != 0 && strcmp(style,"movie") != 0)
error->all(FLERR,"Invalid attribute in dump custom command");
error->all(FLERR,"Invalid attribute {} in dump {} command",earg[ioptional],style);
// noptional = # of optional args
// reset nfield to subtract off optional args
@ -238,9 +238,8 @@ DumpCustom::~DumpCustom()
for (int i = 0; i < ncustom; i++) delete[] id_custom[i];
memory->sfree(id_custom);
delete [] custom;
delete [] custom_flag;
memory->sfree(custom);
memory->sfree(custom_flag);
memory->destroy(choose);
memory->destroy(dchoose);
memory->destroy(clist);
@ -909,32 +908,27 @@ int DumpCustom::count()
} else if (thresh_array[ithresh] == Q) {
if (!atom->q_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = atom->q;
nstride = 1;
} else if (thresh_array[ithresh] == MUX) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][0];
nstride = 4;
} else if (thresh_array[ithresh] == MUY) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][1];
nstride = 4;
} else if (thresh_array[ithresh] == MUZ) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][2];
nstride = 4;
} else if (thresh_array[ithresh] == MU) {
if (!atom->mu_flag)
error->all(FLERR,
"Threshold for an atom property that isn't allocated");
error->all(FLERR,"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][3];
nstride = 4;
@ -1521,7 +1515,7 @@ int DumpCustom::parse_fields(int narg, char **arg)
field2index[iarg] = add_variable(name);
break;
// custom per-atom floating point vector or array
// custom per-atom floating point vector or array = d_ID d2_ID
case ArgInfo::DNAME:
pack_choice[iarg] = &DumpCustom::pack_custom;
@ -1533,18 +1527,18 @@ int DumpCustom::parse_fields(int narg, char **arg)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[iarg] == 0) {
if (!flag || cols)
error->all(FLERR,"Property double vector for dump custom does not exist");
error->all(FLERR,"Property double vector {} for dump custom does not exist",name);
} else {
if (!flag || !cols)
error->all(FLERR,"Property double array for dump custom does not exist");
error->all(FLERR,"Property double array {} for dump custom does not exist",name);
if (argindex[iarg] > atom->dcols[n])
error->all(FLERR,"Dump custom property array is accessed out-of-range");
error->all(FLERR,"Dump custom property array {} is accessed out-of-range",name);
}
field2index[iarg] = add_custom(name,1);
break;
// custom per-atom integer vector or array
// custom per-atom integer vector or array = i_ID or i2_ID
case ArgInfo::INAME:
pack_choice[iarg] = &DumpCustom::pack_custom;
@ -1556,15 +1550,12 @@ int DumpCustom::parse_fields(int narg, char **arg)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[iarg] == 0) {
if (flag || cols)
error->all(FLERR,
"Property integer vector for dump custom does not exist");
error->all(FLERR,"Property integer vector {} for dump custom does not exist",name);
} else {
if (flag || !cols)
error->all(FLERR,
"Property integer array for dump custom does not exist");
error->all(FLERR,"Property integer array {} for dump custom does not exist",name);
if (argindex[iarg] > atom->icols[n])
error->all(FLERR,
"Dump custom property array is accessed out-of-range");
error->all(FLERR,"Dump custom property array {} is accessed out-of-range",name);
}
field2index[iarg] = add_custom(name,0);
@ -1574,6 +1565,7 @@ int DumpCustom::parse_fields(int narg, char **arg)
default:
return iarg;
break;
}
}
}
@ -1667,13 +1659,9 @@ int DumpCustom::add_custom(const char *id, int flag)
if (strcmp(id,id_custom[icustom]) == 0) break;
if (icustom < ncustom) return icustom;
id_custom = (char **)
memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom");
delete [] custom;
custom = new int[ncustom+1];
delete [] custom_flag;
custom_flag = new int[ncustom+1];
id_custom = (char **) memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom");
custom = (int *) memory->srealloc(custom,(ncustom+1)*sizeof(int),"dump:custom");
custom_flag = (int *) memory->srealloc(custom_flag,(ncustom+1)*sizeof(int),"dump:custom_flag");
id_custom[ncustom] = utils::strdup(id);
custom_flag[ncustom] = flag;
@ -1962,21 +1950,18 @@ int DumpCustom::modify_param(int narg, char **arg)
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[nfield+nthresh] == 0) {
if (flag || cols)
error->all(FLERR,
"Property double vector for dump custom does not exist");
if (!flag || cols)
error->all(FLERR,"Property double vector for dump custom does not exist");
thresh_array[nthresh] = DVEC;
} else {
if (flag || !cols)
error->all(FLERR,
"Property double array for dump custom does not exist");
if (!flag || !cols)
error->all(FLERR,"Property double array for dump custom does not exist");
if (argindex[nfield+nthresh] > atom->dcols[n])
error->all(FLERR,
"Dump custom property array is accessed out-of-range");
error->all(FLERR,"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = DARRAY;
}
field2index[nfield+nthresh] = add_custom(name,0);
field2index[nfield+nthresh] = add_custom(name,thresh_array[nthresh]);
break;
// custom per atom integer vector or array
@ -1988,20 +1973,17 @@ int DumpCustom::modify_param(int narg, char **arg)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[nfield+nthresh] == 0) {
if (flag || cols)
error->all(FLERR,
"Property integer vector for dump custom does not exist");
error->all(FLERR,"Property integer vector for dump custom does not exist");
thresh_array[nthresh] = IVEC;
} else {
if (flag || !cols)
error->all(FLERR,
"Property integer array for dump custom does not exist");
error->all(FLERR,"Property integer array for dump custom does not exist");
if (argindex[nfield+nthresh] > atom->icols[n])
error->all(FLERR,
"Dump custom property array is accessed out-of-range");
error->all(FLERR,"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = IARRAY;
}
field2index[nfield+nthresh] = add_custom(name,0);
field2index[nfield+nthresh] = add_custom(name,thresh_array[nthresh]);
break;
// no match

View File

@ -111,9 +111,9 @@ FixVector::FixVector(LAMMPS *lmp, int narg, char **arg) :
for (int i = 0; i < nvalues; i++) {
if (which[i] == ArgInfo::COMPUTE) {
Compute *compute = modify->compute[modify->find_compute(ids[i])];
if (argindex[0] == 0) value = compute->extscalar;
if (argindex[i] == 0) value = compute->extscalar;
else if (compute->extvector >= 0) value = compute->extvector;
else value = compute->extlist[argindex[0]-1];
else value = compute->extlist[argindex[i]-1];
} else if (which[i] == ArgInfo::FIX) {
Fix *fix = modify->fix[modify->find_fix(ids[i])];
if (argindex[i] == 0) value = fix->extvector;

View File

@ -299,6 +299,7 @@ void Info::command(int narg, char **arg)
if (has_png_support()) fputs("-DLAMMPS_PNG\n",out);
if (has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",out);
if (has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",out);
if (has_fft_single_support()) fputs("-DFFT_SINGLE\n",out);
if (has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",out);
#if defined(LAMMPS_BIGBIG)
@ -895,6 +896,8 @@ bool Info::is_available(const char *category, const char *name)
return has_jpeg_support();
} else if (strcmp(name,"ffmpeg") == 0) {
return has_ffmpeg_support();
} else if (strcmp(name,"fft_single") == 0) {
return has_fft_single_support();
} else if (strcmp(name,"exceptions") == 0) {
return has_exceptions();
}
@ -1143,6 +1146,14 @@ bool Info::has_ffmpeg_support() {
#endif
}
bool Info::has_fft_single_support() {
#ifdef FFT_SINGLE
return true;
#else
return false;
#endif
}
bool Info::has_exceptions() {
#ifdef LAMMPS_EXCEPTIONS
return true;
@ -1162,12 +1173,14 @@ bool Info::has_package(const std::string &package_name) {
#if defined(LMP_GPU)
extern bool lmp_gpu_config(const std::string &, const std::string &);
extern bool lmp_has_gpu_device();
extern bool lmp_has_compatible_gpu_device();
extern std::string lmp_gpu_device_info();
// we will only report compatible GPUs, i.e. when a GPU device is
// available *and* supports the required floating point precision
bool Info::has_gpu_device()
{
return lmp_has_gpu_device();
return lmp_has_compatible_gpu_device();
}
std::string Info::get_gpu_device_info()

View File

@ -42,6 +42,7 @@ class Info : public Command {
static bool has_png_support();
static bool has_jpeg_support();
static bool has_ffmpeg_support();
static bool has_fft_single_support();
static bool has_exceptions();
static bool has_package(const std::string &);
static bool has_accelerator_feature(const std::string &, const std::string &,

View File

@ -51,6 +51,10 @@
#include "update.h"
#include "version.h"
#if defined(LMP_PLUGIN)
#include "plugin.h"
#endif
#include <cctype>
#include <cmath>
#include <cstring>
@ -65,6 +69,12 @@
#include "lmpinstalledpkgs.h"
#include "lmpgitversion.h"
#if defined(LAMMPS_UPDATE)
#define UPDATE_STRING " - " LAMMPS_UPDATE
#else
#define UPDATE_STRING ""
#endif
static void print_style(FILE *fp, const char *str, int &pos);
struct LAMMPS_NS::package_styles_lists {
@ -511,7 +521,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) :
}
if ((universe->me == 0) && !helpflag)
utils::logmesg(this,fmt::format("LAMMPS ({})\n",version));
utils::logmesg(this,fmt::format("LAMMPS ({}{})\n",version,UPDATE_STRING));
// universe is one or more worlds, as setup by partition switch
// split universe communicator into separate world communicators
@ -905,6 +915,10 @@ void LAMMPS::init()
void LAMMPS::destroy()
{
// must wipe out all plugins first, if configured
#if defined(LMP_PLUGIN)
plugin_clear(this);
#endif
delete update;
update = nullptr;
@ -1147,10 +1161,10 @@ void _noopt LAMMPS::help()
if (has_git_info) {
fprintf(fp,"\nLarge-scale Atomic/Molecular Massively Parallel Simulator - "
LAMMPS_VERSION "\nGit info (%s / %s)\n\n",git_branch, git_descriptor);
LAMMPS_VERSION UPDATE_STRING "\nGit info (%s / %s)\n\n",git_branch, git_descriptor);
} else {
fprintf(fp,"\nLarge-scale Atomic/Molecular Massively Parallel Simulator - "
LAMMPS_VERSION "\n\n");
LAMMPS_VERSION UPDATE_STRING "\n\n");
}
fprintf(fp,
"Usage example: %s -var t 300 -echo screen -in in.alloy\n\n"
@ -1350,7 +1364,7 @@ void LAMMPS::print_config(FILE *fp)
fmt::print(fp,"Accelerator configuration:\n\n{}\n",
Info::get_accelerator_info());
#if defined(LMP_GPU)
fmt::print(fp,"GPU present: {}\n\n",Info::has_gpu_device() ? "yes" : "no");
fmt::print(fp,"Compatible GPU present: {}\n\n",Info::has_gpu_device() ? "yes" : "no");
#endif
fputs("Active compile time flags:\n\n",fp);
@ -1358,6 +1372,7 @@ void LAMMPS::print_config(FILE *fp)
if (Info::has_png_support()) fputs("-DLAMMPS_PNG\n",fp);
if (Info::has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",fp);
if (Info::has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",fp);
if (Info::has_fft_single_support()) fputs("-DFFT_SINGLE\n",fp);
if (Info::has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",fp);
#if defined(LAMMPS_BIGBIG)
fputs("-DLAMMPS_BIGBIG\n",fp);

View File

@ -676,7 +676,10 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
}
for (int index = nlo; index <= nhi; index++) {
earg[newarg] = utils::strdup(fmt::format("{}2_{}[{}]{}", word[0], id, index, tail));
if (word[1] == '2')
earg[newarg] = utils::strdup(fmt::format("{}2_{}[{}]{}", word[0], id, index, tail));
else
earg[newarg] = utils::strdup(fmt::format("{}_{}[{}]{}", word[0], id, index, tail));
newarg++;
}
} else {

View File

@ -1 +1,2 @@
#define LAMMPS_VERSION "29 Sep 2021"
#define LAMMPS_UPDATE "Update 1"

View File

@ -269,7 +269,7 @@ void WriteRestart::write(const std::string &file)
double *buf;
memory->create(buf,max_size,"write_restart:buf");
memset(buf,0,max_size*sizeof(buf));
memset(buf,0,max_size*sizeof(double));
// all procs write file layout info which may include per-proc sizes

View File

@ -8,12 +8,12 @@ fi
export GIT_CONFIG_COUNT=1
export GIT_CONFIG_KEY_0="url.$GITHUB_PROXY_DIR/.insteadOf"
export GIT_CONFIG_VALUE_0=git://github.com/
export GIT_CONFIG_VALUE_0=https://github.com/
echo "Redirecting git://github.com urls to local cache..."
echo "Redirecting https://github.com urls to local cache..."
function deactivate_git_cache {
echo "Removing git://github.com redirect..."
echo "Removing https://github.com redirect..."
unset GIT_CONFIG_COUNT
unset GIT_CONFIG_KEY_0
unset GIT_CONFIG_VALUE_0

View File

@ -63,7 +63,7 @@ echo "or"
echo
echo "-D LAMMPS_DOWNLOADS_URL=${HTTP_CACHE_URL} -C \"${LAMMPS_HTTP_CACHE_CONFIG}\""
echo
echo "pip installations and git clones (from git://) are automatically redirected"
echo "pip installations and git clones (from https://) are automatically redirected"
echo
echo Use 'deactivate_caches' to revert changes
echo

View File

@ -21,7 +21,7 @@ built CentOS 7.x singularity container.
```
cd some/work/directory
git clone --depth 500 git://github.com/lammps/lammps.git lammps
git clone --depth 500 https://github.com/lammps/lammps.git lammps
mkdir build-centos7
cd build-centos7
sudo singularity build centos7.sif ../tools/singularity/centos7.def

View File

@ -8,7 +8,7 @@ add_test(NAME RunLammps
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_tests_properties(RunLammps PROPERTIES
ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=1"
PASS_REGULAR_EXPRESSION "^LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]\\)")
PASS_REGULAR_EXPRESSION "LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]( - Update [0-9]+)?\\)")
# check if the compiled executable will print the help message
add_test(NAME HelpMessage
@ -31,6 +31,10 @@ if(BUILD_MPI)
set(MPI_TEST_NUM_PROCS 1)
set(MPI_TEST_WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
cmake_parse_arguments(MPI_TEST "" "NAME;NUM_PROCS;WORKING_DIRECTORY" "COMMAND" ${ARGN})
# Do not add test when oversubscribing
if(MPI_TEST_NUMPROCS GREATER MPIEXEC_MAX_NUMPROCS)
return()
endif()
list(GET MPI_TEST_COMMAND 0 EXECUTABLE)
list(REMOVE_AT MPI_TEST_COMMAND 0)
set(ARGS ${MPI_TEST_COMMAND})

View File

@ -246,7 +246,7 @@ TEST_F(GroupTest, Molecular)
ASSERT_DOUBLE_EQ(group->mass(group->find("half")), 40);
ASSERT_DOUBLE_EQ(group->mass(group->find("half"), domain->find_region("top")), 10);
ASSERT_NEAR(group->charge(group->find("top")), 0, 1.0e-14);
ASSERT_DOUBLE_EQ(group->charge(group->find("right"), domain->find_region("top")), 0);
ASSERT_NEAR(group->charge(group->find("right"), domain->find_region("top")), 0, 1.0e-14);
TEST_FAILURE(".*ERROR: Illegal group command.*", command("group three include xxx"););
}

View File

@ -858,6 +858,13 @@ TEST(PairStyle, gpu)
if (!Info::has_gpu_device()) GTEST_SKIP();
if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP();
// when testing PPPM styles with GPUs and GPU support is compiled with single precision
// we also must have single precision FFTs; otherwise skip since the test would abort
if (utils::strmatch(test_config.basename, ".*pppm.*") &&
(Info::has_accelerator_feature("GPU", "precision", "single")) &&
(!Info::has_fft_single_support()))
GTEST_SKIP();
const char *args_neigh[] = {"PairStyle", "-log", "none", "-echo",
"screen", "-nocite", "-sf", "gpu"};
const char *args_noneigh[] = {"PairStyle", "-log", "none", "-echo", "screen", "-nocite", "-sf",

View File

@ -166,9 +166,9 @@ class PythonCapabilities(unittest.TestCase):
self.assertIn('single',settings['GPU']['precision'])
if self.cmake_cache['PKG_KOKKOS']:
if self.cmake_cache['Kokkos_ENABLE_OPENMP']:
if 'Kokkos_ENABLE_OPENMP' in self.cmake_cache and self.cmake_cache['Kokkos_ENABLE_OPENMP']:
self.assertIn('openmp',settings['KOKKOS']['api'])
if self.cmake_cache['Kokkos_ENABLE_SERIAL']:
if 'Kokkos_ENABLE_SERIAL' in self.cmake_cache and self.cmake_cache['Kokkos_ENABLE_SERIAL']:
self.assertIn('serial',settings['KOKKOS']['api'])
self.assertIn('double',settings['KOKKOS']['precision'])