Merge branch 'develop' into fix-pair-dump-skip
This commit is contained in:
@ -15,6 +15,10 @@
|
||||
|
||||
#include "atom.h"
|
||||
#include "citeme.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "pair.h"
|
||||
#include "pair_hybrid.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -87,6 +91,42 @@ AtomVecDielectric::AtomVecDielectric(LAMMPS *_lmp) : AtomVec(_lmp)
|
||||
bond_per_atom = angle_per_atom = dihedral_per_atom = improper_per_atom = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecDielectric::init()
|
||||
{
|
||||
AtomVec::init();
|
||||
|
||||
// since atom style dielectric modifies the charge q, it will produce incorrect results
|
||||
// with pair styles using coulomb without dielectric support.
|
||||
|
||||
std::string pair_style(force->pair_style);
|
||||
if ((pair_style != "none") && (pair_style != "zero") && !utils::strmatch(force->pair_style,"/dielectric")) {
|
||||
bool mismatch = false;
|
||||
if (utils::strmatch(force->pair_style,"^reaxff")) mismatch = true;
|
||||
if (utils::strmatch(force->pair_style,"^comb")) mismatch = true;
|
||||
if (utils::strmatch(force->pair_style,"coul")) mismatch = true;
|
||||
if (utils::strmatch(force->pair_style,"tip4p")) mismatch = true;
|
||||
if (utils::strmatch(force->pair_style,"dipole")) mismatch = true;
|
||||
|
||||
if (utils::strmatch(force->pair_style,"^hybrid")) {
|
||||
auto hybrid = dynamic_cast<PairHybrid *>(force->pair);
|
||||
if (hybrid) {
|
||||
for (int i = 0; i < hybrid->nstyles; i++) {
|
||||
if (utils::strmatch(hybrid->keywords[i],"^reaxff")) mismatch = true;
|
||||
if (utils::strmatch(hybrid->keywords[i],"^comb")) mismatch = true;
|
||||
if (utils::strmatch(hybrid->keywords[i],"coul")) mismatch = true;
|
||||
if (utils::strmatch(hybrid->keywords[i],"tip4p")) mismatch = true;
|
||||
if (utils::strmatch(hybrid->keywords[i],"dipole")) mismatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mismatch)
|
||||
error->all(FLERR, "Pair style {} is not compatible with atom style {}",
|
||||
pair_style, atom->get_style());
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set local copies of all grow ptrs used by this class, except defaults
|
||||
needed in replicate when 2 atom classes exist and it calls pack_restart()
|
||||
|
||||
@ -31,6 +31,7 @@ class AtomVecDielectric : public AtomVec {
|
||||
public:
|
||||
AtomVecDielectric(class LAMMPS *);
|
||||
|
||||
void init() override;
|
||||
void grow_pointers() override;
|
||||
void create_atom_post(int) override;
|
||||
void data_atom_post(int) override;
|
||||
|
||||
@ -38,6 +38,7 @@ static constexpr double EPSILON = 1.0e-6;
|
||||
PairCoulCutDielectric::PairCoulCutDielectric(LAMMPS *_lmp) : PairCoulCut(_lmp), efield(nullptr)
|
||||
{
|
||||
nmax = 0;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -41,6 +41,7 @@ PairCoulLongDielectric::PairCoulLongDielectric(LAMMPS *_lmp) :
|
||||
{
|
||||
nmax = 0;
|
||||
single_enable = 0;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -40,6 +40,7 @@ PairLJCutCoulCutDielectric::PairLJCutCoulCutDielectric(LAMMPS *_lmp) : PairLJCut
|
||||
efield = nullptr;
|
||||
epot = nullptr;
|
||||
nmax = 0;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -93,15 +94,16 @@ void PairLJCutCoulCutDielectric::compute(int eflag, int vflag)
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
qtmp = q[i];
|
||||
etmp = eps[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
etmp = eps[i];
|
||||
itype = type[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
// self term Eq. (55) for I_{ii} and Eq. (52) and in Barros et al
|
||||
|
||||
double curvature_threshold = sqrt(area[i]);
|
||||
if (curvature[i] < curvature_threshold) {
|
||||
double sf = curvature[i] / (4.0 * MY_PIS * curvature_threshold) * area[i] * q[i];
|
||||
|
||||
@ -40,6 +40,7 @@ PairLJCutCoulDebyeDielectric::PairLJCutCoulDebyeDielectric(LAMMPS *_lmp) : PairL
|
||||
efield = nullptr;
|
||||
epot = nullptr;
|
||||
nmax = 0;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -45,6 +45,7 @@ PairLJCutCoulLongDielectric::PairLJCutCoulLongDielectric(LAMMPS *_lmp) : PairLJC
|
||||
efield = nullptr;
|
||||
epot = nullptr;
|
||||
nmax = 0;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -47,6 +47,7 @@ PairLJCutCoulMSMDielectric::PairLJCutCoulMSMDielectric(LAMMPS *_lmp) : PairLJCut
|
||||
nmax = 0;
|
||||
ftmp = nullptr;
|
||||
efield = nullptr;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -45,6 +45,7 @@ PairLJLongCoulLongDielectric::PairLJLongCoulLongDielectric(LAMMPS *_lmp) : PairL
|
||||
efield = nullptr;
|
||||
epot = nullptr;
|
||||
nmax = 0;
|
||||
no_virial_fdotr_compute = 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
||||
@ -25,7 +25,7 @@ using namespace FixConst;
|
||||
|
||||
enum { NATIVE, REAL, METAL }; // LAMMPS units which MDI supports
|
||||
|
||||
#define MAXELEMENT 103 // used elsewhere in MDI package
|
||||
#define MAXELEMENT 103 // used elsewhere in MDI package
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -33,8 +33,7 @@ FixMDIQM::FixMDIQM(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
|
||||
{
|
||||
// check requirements for LAMMPS to work with MDI as an engine
|
||||
|
||||
if (atom->tag_enable == 0)
|
||||
error->all(FLERR, "Cannot use MDI engine without atom IDs");
|
||||
if (atom->tag_enable == 0) error->all(FLERR, "Cannot use MDI engine without atom IDs");
|
||||
if (atom->natoms && atom->tag_consecutive() == 0)
|
||||
error->all(FLERR, "MDI engine requires consecutive atom IDs");
|
||||
|
||||
@ -55,41 +54,51 @@ FixMDIQM::FixMDIQM(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
|
||||
|
||||
int iarg = 3;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"virial") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) virialflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) virialflag = 0;
|
||||
else error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg], "virial") == 0) {
|
||||
if (iarg + 2 > narg) error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg + 1], "yes") == 0)
|
||||
virialflag = 1;
|
||||
else if (strcmp(arg[iarg + 1], "no") == 0)
|
||||
virialflag = 0;
|
||||
else
|
||||
error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"add") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) addflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) addflag = 0;
|
||||
else error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
} else if (strcmp(arg[iarg], "add") == 0) {
|
||||
if (iarg + 2 > narg) error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg + 1], "yes") == 0)
|
||||
addflag = 1;
|
||||
else if (strcmp(arg[iarg + 1], "no") == 0)
|
||||
addflag = 0;
|
||||
else
|
||||
error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"every") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
every = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
|
||||
if (every <= 0) error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
} else if (strcmp(arg[iarg], "every") == 0) {
|
||||
if (iarg + 2 > narg) error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
every = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
if (every <= 0) error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"connect") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) connectflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) connectflag = 0;
|
||||
else error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
} else if (strcmp(arg[iarg], "connect") == 0) {
|
||||
if (iarg + 2 > narg) error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
if (strcmp(arg[iarg + 1], "yes") == 0)
|
||||
connectflag = 1;
|
||||
else if (strcmp(arg[iarg + 1], "no") == 0)
|
||||
connectflag = 0;
|
||||
else
|
||||
error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"elements") == 0) {
|
||||
} else if (strcmp(arg[iarg], "elements") == 0) {
|
||||
int ntypes = atom->ntypes;
|
||||
if (iarg+ntypes+1 > narg) error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
delete [] elements;
|
||||
elements = new int[ntypes+1];
|
||||
if (iarg + ntypes + 1 > narg) error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
delete[] elements;
|
||||
elements = new int[ntypes + 1];
|
||||
for (int i = 1; i <= ntypes; i++) {
|
||||
elements[i] = utils::inumeric(FLERR,arg[iarg+i],false,lmp);
|
||||
elements[i] = utils::inumeric(FLERR, arg[iarg + i], false, lmp);
|
||||
if (elements[i] < 1 || elements[i] > MAXELEMENT)
|
||||
error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
}
|
||||
iarg += ntypes+1;
|
||||
} else error->all(FLERR,"Illegal fix mdi/qm command");
|
||||
iarg += ntypes + 1;
|
||||
} else
|
||||
error->all(FLERR, "Illegal fix mdi/qm command");
|
||||
}
|
||||
|
||||
// fix output settings are based on optional keywords
|
||||
@ -217,26 +226,26 @@ void FixMDIQM::init()
|
||||
plugin = 1;
|
||||
int method;
|
||||
MDI_Get_method(&method, mdicomm);
|
||||
if (method != MDI_PLUGIN)
|
||||
error->all(FLERR, "MDI internal error for plugin engine");
|
||||
if (method != MDI_PLUGIN) error->all(FLERR, "MDI internal error for plugin engine");
|
||||
}
|
||||
|
||||
// connection should have been already made by "mdi connect" command
|
||||
// only works for stand-alone engines
|
||||
// connection should have been already made by "mdi connect" command
|
||||
// only works for stand-alone engines
|
||||
|
||||
} else {
|
||||
plugin = 0;
|
||||
|
||||
if (lmp->mdicomm == nullptr)
|
||||
error->all(FLERR,"Fix mdi/qm is not connected to engine via mdi connect");
|
||||
error->all(FLERR, "Fix mdi/qm is not connected to engine via mdi connect");
|
||||
|
||||
int nbytes = sizeof(MDI_Comm);
|
||||
char *ptrcomm = (char *) lmp->mdicomm;
|
||||
memcpy(&mdicomm,ptrcomm,nbytes);
|
||||
memcpy(&mdicomm, ptrcomm, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
// send natoms, atom types or elements, and simulation box to engine
|
||||
// confirm engine count of NATOMS is correct
|
||||
// this will trigger setup of a new system
|
||||
// subsequent calls in post_force() will be for same system until new init()
|
||||
|
||||
@ -245,36 +254,41 @@ void FixMDIQM::init()
|
||||
int natoms_exists;
|
||||
int ierr = MDI_Check_command_exists("@DEFAULT", ">NATOMS", mdicomm, &natoms_exists);
|
||||
if (ierr) error->all(FLERR, "MDI: >NATOMS command check");
|
||||
if ( natoms_exists ) {
|
||||
MPI_Bcast(&natoms_exists, 1, MPI_INT, 0, world);
|
||||
|
||||
if (natoms_exists) {
|
||||
ierr = MDI_Send_command(">NATOMS", mdicomm);
|
||||
if (ierr) error->all(FLERR, "MDI: >NATOMS command");
|
||||
int n = static_cast<int> (atom->natoms);
|
||||
int n = static_cast<int>(atom->natoms);
|
||||
ierr = MDI_Send(&n, 1, MDI_INT, mdicomm);
|
||||
if (ierr) error->all(FLERR, "MDI: >NATOMS data");
|
||||
|
||||
} else { // confirm that the engine's NATOMS is correct
|
||||
|
||||
} else {
|
||||
ierr = MDI_Send_command("<NATOMS", mdicomm);
|
||||
if (ierr) error->all(FLERR, "MDI: <NATOMS command");
|
||||
int n;
|
||||
ierr = MDI_Recv(&n, 1, MDI_INT, mdicomm);
|
||||
if (ierr) error->all(FLERR, "MDI: <NATOMS data");
|
||||
if ( n != atom->natoms ) error->all(FLERR, "MDI: Engine has the wrong number of atoms, and does not support the >NATOMS command.");
|
||||
MPI_Bcast(&n, 1, MPI_INT, 0, world);
|
||||
|
||||
if (n != atom->natoms)
|
||||
error->all(FLERR, "MDI: Engine has wrong atom count and does not support >NATOMS command");
|
||||
}
|
||||
|
||||
int elements_exists;
|
||||
int types_exists;
|
||||
ierr = MDI_Check_command_exists("@DEFAULT", ">ELEMENTS", mdicomm, &elements_exists);
|
||||
if (ierr) error->all(FLERR, "MDI: >ELEMENTS command check");
|
||||
MPI_Bcast(&elements_exists, 1, MPI_INT, 0, world);
|
||||
|
||||
ierr = MDI_Check_command_exists("@DEFAULT", ">TYPES", mdicomm, &types_exists);
|
||||
if (ierr) error->all(FLERR, "MDI: >TYPES command check");
|
||||
if ( elements && elements_exists ) {
|
||||
send_elements();
|
||||
} else if ( types_exists ) {
|
||||
send_types();
|
||||
}
|
||||
MPI_Bcast(&types_exists, 1, MPI_INT, 0, world);
|
||||
|
||||
if (elements && elements_exists)
|
||||
send_elements();
|
||||
else if (types_exists)
|
||||
send_types();
|
||||
send_box();
|
||||
}
|
||||
|
||||
@ -301,8 +315,7 @@ void FixMDIQM::post_force(int vflag)
|
||||
|
||||
// if simulation box dynamically changes, send current box to MDI engine
|
||||
|
||||
if (domain->box_change_size || domain->box_change_shape)
|
||||
send_box();
|
||||
if (domain->box_change_size || domain->box_change_shape) send_box();
|
||||
|
||||
// gather all coords, ordered by atomID
|
||||
|
||||
@ -319,7 +332,7 @@ void FixMDIQM::post_force(int vflag)
|
||||
buf3[3 * index + 2] = x[i][2] * lmp2mdi_length;
|
||||
}
|
||||
|
||||
int n = static_cast<int> (atom->natoms);
|
||||
int n = static_cast<int>(atom->natoms);
|
||||
MPI_Reduce(buf3, buf3all, 3 * n, MPI_DOUBLE, MPI_SUM, 0, world);
|
||||
|
||||
// send current coords to MDI engine
|
||||
@ -358,7 +371,6 @@ void FixMDIQM::post_force(int vflag)
|
||||
fqm[i][2] = buf3[3 * index + 2] * mdi2lmp_force;
|
||||
}
|
||||
|
||||
|
||||
// optionally add forces to owned atoms
|
||||
// use atomID of local atoms to index into ordered buf3
|
||||
|
||||
@ -372,7 +384,8 @@ void FixMDIQM::post_force(int vflag)
|
||||
}
|
||||
}
|
||||
|
||||
// optionally request stress tensor from MDI engine, convert to virial
|
||||
// optionally request stress tensor from MDI engine, convert to 6-value virial
|
||||
// MDI defines virial tensor as intensive (divided by volume), LAMMPS does not
|
||||
// qm_virial = fix output for global QM virial
|
||||
|
||||
if (virialflag) {
|
||||
@ -385,9 +398,9 @@ void FixMDIQM::post_force(int vflag)
|
||||
qm_virial_symmetric[0] = qm_virial[0] * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[1] = qm_virial[4] * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[2] = qm_virial[8] * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[3] = 0.5*(qm_virial[1]+qm_virial[3]) * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[4] = 0.5*(qm_virial[2]+qm_virial[6]) * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[5] = 0.5*(qm_virial[5]+qm_virial[7]) * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[3] = 0.5 * (qm_virial[1] + qm_virial[3]) * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[4] = 0.5 * (qm_virial[2] + qm_virial[6]) * mdi2lmp_pressure;
|
||||
qm_virial_symmetric[5] = 0.5 * (qm_virial[5] + qm_virial[7]) * mdi2lmp_pressure;
|
||||
}
|
||||
|
||||
// optionally set fix->virial
|
||||
@ -402,8 +415,7 @@ void FixMDIQM::post_force(int vflag)
|
||||
volume = domain->xprd * domain->yprd;
|
||||
else if (domain->dimension == 3)
|
||||
volume = domain->xprd * domain->yprd * domain->zprd;
|
||||
for (int i = 0; i < 6; i++)
|
||||
virial[i] = qm_virial_symmetric[i]*volume/nprocs;
|
||||
for (int i = 0; i < 6; i++) virial[i] = qm_virial_symmetric[i] * volume / nprocs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,10 +459,9 @@ void FixMDIQM::reallocate()
|
||||
|
||||
if (atom->natoms > maxbuf) {
|
||||
bigint nsize = atom->natoms * 3;
|
||||
if (nsize > MAXSMALLINT)
|
||||
error->all(FLERR, "Natoms too large to use with fix mdi/qm");
|
||||
if (nsize > MAXSMALLINT) error->all(FLERR, "Natoms too large to use with fix mdi/qm");
|
||||
|
||||
maxbuf = static_cast<int> (atom->natoms);
|
||||
maxbuf = static_cast<int>(atom->natoms);
|
||||
memory->destroy(ibuf1);
|
||||
memory->destroy(buf3);
|
||||
memory->destroy(buf3all);
|
||||
@ -467,7 +478,7 @@ void FixMDIQM::reallocate()
|
||||
|
||||
void FixMDIQM::send_types()
|
||||
{
|
||||
int n = static_cast<int> (atom->natoms);
|
||||
int n = static_cast<int>(atom->natoms);
|
||||
memset(ibuf1, 0, n * sizeof(int));
|
||||
|
||||
// use local atomID to index into ordered ibuf1
|
||||
@ -496,7 +507,7 @@ void FixMDIQM::send_types()
|
||||
|
||||
void FixMDIQM::send_elements()
|
||||
{
|
||||
int n = static_cast<int> (atom->natoms);
|
||||
int n = static_cast<int>(atom->natoms);
|
||||
memset(ibuf1, 0, n * sizeof(int));
|
||||
|
||||
// use local atomID to index into ordered ibuf1
|
||||
@ -530,7 +541,9 @@ void FixMDIQM::send_box()
|
||||
int celldispl_exists;
|
||||
int ierr = MDI_Check_command_exists("@DEFAULT", ">NATOMS", mdicomm, &celldispl_exists);
|
||||
if (ierr) error->all(FLERR, "MDI: >CELL_DISPL command check");
|
||||
if ( celldispl_exists ) {
|
||||
MPI_Bcast(&celldispl_exists, 1, MPI_INT, 0, world);
|
||||
|
||||
if (celldispl_exists) {
|
||||
ierr = MDI_Send_command(">CELL_DISPL", mdicomm);
|
||||
if (ierr) error->all(FLERR, "MDI: >CELL_DISPL command");
|
||||
cell[0] = domain->boxlo[0] * lmp2mdi_length;
|
||||
@ -608,18 +621,17 @@ void FixMDIQM::unit_conversions()
|
||||
mdi2lmp_force = angstrom_to_bohr / ev_to_hartree;
|
||||
}
|
||||
|
||||
// pressure or stress units = force/area = energy/volume
|
||||
// stress units = force/area = energy/volume
|
||||
|
||||
mdi2lmp_pressure = 1.0;
|
||||
lmp2mdi_pressure = 1.0;
|
||||
|
||||
if (lmpunits == REAL) {
|
||||
lmp2mdi_pressure = (kelvin_to_hartree / force->boltz) /
|
||||
(angstrom_to_bohr * angstrom_to_bohr * angstrom_to_bohr) / force->nktv2p;
|
||||
(angstrom_to_bohr * angstrom_to_bohr * angstrom_to_bohr);
|
||||
mdi2lmp_pressure = 1.0 / lmp2mdi_pressure;
|
||||
} else if (lmpunits == METAL) {
|
||||
lmp2mdi_pressure =
|
||||
ev_to_hartree / (angstrom_to_bohr * angstrom_to_bohr * angstrom_to_bohr) / force->nktv2p;
|
||||
lmp2mdi_pressure = ev_to_hartree / (angstrom_to_bohr * angstrom_to_bohr * angstrom_to_bohr);
|
||||
mdi2lmp_pressure = 1.0 / lmp2mdi_pressure;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class FixMDIQM : public Fix {
|
||||
|
||||
private:
|
||||
int nprocs;
|
||||
int every,virialflag,addflag,connectflag;
|
||||
int every, virialflag, addflag, connectflag;
|
||||
int plugin;
|
||||
int maxlocal;
|
||||
int sumflag;
|
||||
@ -48,7 +48,7 @@ class FixMDIQM : public Fix {
|
||||
|
||||
double qm_energy;
|
||||
int lmpunits;
|
||||
double qm_virial[9],qm_virial_symmetric[6];
|
||||
double qm_virial[9], qm_virial_symmetric[6];
|
||||
double **fqm;
|
||||
|
||||
MDI_Comm mdicomm;
|
||||
|
||||
@ -23,12 +23,8 @@
|
||||
#define LAMMPS_LIB_MPI 1
|
||||
#include "library.h"
|
||||
|
||||
#include "mdi_engine.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Initialize an instance of LAMMPS as an MDI plugin
|
||||
@ -52,15 +48,16 @@ command-line argument, which must be provided by the MDI driver.
|
||||
* \param class_obj pointer to an instance of an mdi/engine fix cast to ``void *``.
|
||||
* \return 0 on no error. */
|
||||
|
||||
int MDI_Plugin_init_lammps()
|
||||
int MDI_Plugin_init_lammps(void *plugin_state)
|
||||
{
|
||||
// initialize MDI
|
||||
|
||||
int mdi_argc;
|
||||
char **mdi_argv;
|
||||
|
||||
if (MDI_Set_plugin_state(plugin_state)) MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
if (MDI_Plugin_get_argc(&mdi_argc)) MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
if (MDI_Plugin_get_argv(&mdi_argv)) MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
if (MDI_Init(&mdi_argc, &mdi_argv)) MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
|
||||
// get the MPI intra-communicator for this code
|
||||
|
||||
@ -90,14 +87,23 @@ int MDI_Plugin_init_lammps()
|
||||
if (!found_filename) MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
|
||||
// create and run a LAMMPS instance
|
||||
// lammps_open() expects a first arg (not used) which is executable name
|
||||
// same as if called from main.cpp
|
||||
// need to add an initial pseudo arg to mdi_argc & mdi_argv
|
||||
// b/c lammps_open() expects first arg to be an executable name
|
||||
// same as if it were called from main.cpp
|
||||
|
||||
int mdi_argc_extra = mdi_argc + 1;
|
||||
char **mdi_argv_extra = new char *[mdi_argc_extra];
|
||||
|
||||
mdi_argv_extra[0] = (char *) "MDI_plugin_engine";
|
||||
for (int i = 0; i < mdi_argc; i++) mdi_argv_extra[i + 1] = mdi_argv[i];
|
||||
|
||||
void *lmp = nullptr;
|
||||
if (lammps_config_has_mpi_support() > 0)
|
||||
lmp = lammps_open(mdi_argc + 1, &mdi_argv[-1], mpi_world_comm, nullptr);
|
||||
lmp = lammps_open(mdi_argc_extra, mdi_argv_extra, mpi_world_comm, nullptr);
|
||||
else
|
||||
lmp = lammps_open_no_mpi(mdi_argc + 1, &mdi_argv[-1], nullptr);
|
||||
lmp = lammps_open_no_mpi(mdi_argc_extra, mdi_argv_extra, nullptr);
|
||||
|
||||
delete[] mdi_argv_extra;
|
||||
|
||||
// process the specified input script
|
||||
// must contain "mdi engine" command
|
||||
@ -110,25 +116,3 @@ int MDI_Plugin_init_lammps()
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Execute an MDI command
|
||||
*
|
||||
\verbatim embed:rst
|
||||
|
||||
This function is called by the MolSSI Driver Interface Library (MDI)
|
||||
when LAMMPS is run as a plugin, and should not otherwise be used.
|
||||
The function executes a single command from an external MDI driver.
|
||||
|
||||
\endverbatim
|
||||
* \param command string buffer corresponding to the command to be executed
|
||||
* \param comm MDI communicator that can be used to communicated with the driver.
|
||||
* \param class_obj pointer to an instance of an mdi/engine fix cast to ``void *``.
|
||||
* \return 0 on no error, 1 on error. */
|
||||
|
||||
int lammps_execute_mdi_command(const char *command, MDI_Comm comm, void *class_obj)
|
||||
{
|
||||
auto mdi_engine = (MDIEngine *) class_obj;
|
||||
return mdi_engine->execute_command(command, comm);
|
||||
}
|
||||
|
||||
@ -14,13 +14,12 @@
|
||||
#ifndef LAMMPS_LIBRARY_MDI_H
|
||||
#define LAMMPS_LIBRARY_MDI_H
|
||||
|
||||
/* C style library calls to LAMMPS when a LAMMPS shared library is
|
||||
* used as a plugin through MolSSI Driver Interface (MDI). */
|
||||
/* C style library call to LAMMPS when a LAMMPS shared library is
|
||||
* used as a plugin through MolSSI Driver Interface (MDI) */
|
||||
|
||||
#include <mdi.h>
|
||||
|
||||
extern "C" {
|
||||
int MDI_Plugin_init_lammps();
|
||||
int lammps_execute_mdi_command(const char *, MDI_Comm, void *);
|
||||
int MDI_Plugin_init_lammps(void *plugin_state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -44,7 +44,7 @@ void MDICommand::command(int narg, char **arg)
|
||||
} else if (strcmp(arg[0], "connect") == 0) {
|
||||
|
||||
if (lmp->mdicomm != nullptr)
|
||||
error->all(FLERR,"MDI cannot connect to already connected engine");
|
||||
error->all(FLERR, "MDI cannot connect to already connected engine");
|
||||
|
||||
MDI_Comm mdicomm;
|
||||
MDI_Get_communicator(&mdicomm, 0);
|
||||
@ -53,23 +53,23 @@ void MDICommand::command(int narg, char **arg)
|
||||
MDI_Accept_communicator(&mdicomm);
|
||||
if (mdicomm == MDI_COMM_NULL)
|
||||
error->all(FLERR, "MDI unable to connect to stand-alone engine");
|
||||
} else error->all(FLERR, "Cannot use mdi connect with plugin engine");
|
||||
} else
|
||||
error->all(FLERR, "Cannot use mdi connect with plugin engine");
|
||||
|
||||
int nbytes = sizeof(MDI_Comm);
|
||||
char *ptrcomm = (char *) memory->smalloc(nbytes,"mdi:mdicomm");
|
||||
memcpy(ptrcomm,&mdicomm,nbytes);
|
||||
char *ptrcomm = (char *) memory->smalloc(nbytes, "mdi:mdicomm");
|
||||
memcpy(ptrcomm, &mdicomm, nbytes);
|
||||
|
||||
lmp->mdicomm = (void *) ptrcomm;
|
||||
|
||||
} else if (strcmp(arg[0], "exit") == 0) {
|
||||
|
||||
if (lmp->mdicomm == nullptr)
|
||||
error->all(FLERR,"MDI cannot send exit to unconnected engine");
|
||||
if (lmp->mdicomm == nullptr) error->all(FLERR, "MDI cannot send exit to unconnected engine");
|
||||
|
||||
MDI_Comm mdicomm;
|
||||
int nbytes = sizeof(MDI_Comm);
|
||||
char *ptrcomm = (char *) lmp->mdicomm;
|
||||
memcpy(&mdicomm,ptrcomm,nbytes);
|
||||
memcpy(&mdicomm, ptrcomm, nbytes);
|
||||
|
||||
int ierr = MDI_Send_command("EXIT", mdicomm);
|
||||
if (ierr) error->all(FLERR, "MDI: EXIT command");
|
||||
@ -77,5 +77,6 @@ void MDICommand::command(int narg, char **arg)
|
||||
memory->sfree(ptrcomm);
|
||||
lmp->mdicomm = nullptr;
|
||||
|
||||
} else error->all(FLERR, "Illegal mdi command");
|
||||
} else
|
||||
error->all(FLERR, "Illegal mdi command");
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ enum { DEFAULT, MD, OPT }; // top-level MDI engine modes
|
||||
|
||||
enum { TYPE, CHARGE, MASS, COORD, VELOCITY, FORCE, ADDFORCE };
|
||||
|
||||
#define MAXELEMENT 103 // used elsewhere in MDI package
|
||||
#define MAXELEMENT 103 // used elsewhere in MDI package
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
trigger LAMMPS to start acting as an MDI engine
|
||||
@ -65,7 +65,7 @@ enum { TYPE, CHARGE, MASS, COORD, VELOCITY, FORCE, ADDFORCE };
|
||||
when EXIT command is received, mdi engine command exits
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
MDIEngine::MDIEngine(LAMMPS *_lmp, int narg, char ** arg) : Pointers(_lmp)
|
||||
MDIEngine::MDIEngine(LAMMPS *_lmp, int narg, char **arg) : Pointers(_lmp)
|
||||
{
|
||||
// check requirements for LAMMPS to work with MDI as an engine
|
||||
|
||||
@ -80,18 +80,19 @@ MDIEngine::MDIEngine(LAMMPS *_lmp, int narg, char ** arg) : Pointers(_lmp)
|
||||
|
||||
int iarg = 0;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"elements") == 0) {
|
||||
if (strcmp(arg[iarg], "elements") == 0) {
|
||||
int ntypes = atom->ntypes;
|
||||
delete [] elements;
|
||||
elements = new int[ntypes+1];
|
||||
if (iarg+ntypes+1 > narg) error->all(FLERR,"Illegal mdi engine command");
|
||||
delete[] elements;
|
||||
elements = new int[ntypes + 1];
|
||||
if (iarg + ntypes + 1 > narg) error->all(FLERR, "Illegal mdi engine command");
|
||||
for (int i = 1; i <= ntypes; i++) {
|
||||
elements[i] = utils::inumeric(FLERR,arg[iarg+i],false,lmp);
|
||||
elements[i] = utils::inumeric(FLERR, arg[iarg + i], false, lmp);
|
||||
if (elements[i] < 0 || elements[i] > MAXELEMENT)
|
||||
error->all(FLERR,"Illegal mdi engine command");
|
||||
error->all(FLERR, "Illegal mdi engine command");
|
||||
}
|
||||
iarg += ntypes+1;
|
||||
} else error->all(FLERR,"Illegal mdi engine command");
|
||||
iarg += ntypes + 1;
|
||||
} else
|
||||
error->all(FLERR, "Illegal mdi engine command");
|
||||
}
|
||||
|
||||
// error check an MDI element does not map to multiple atom types
|
||||
@ -99,10 +100,10 @@ MDIEngine::MDIEngine(LAMMPS *_lmp, int narg, char ** arg) : Pointers(_lmp)
|
||||
if (elements) {
|
||||
int ntypes = atom->ntypes;
|
||||
for (int i = 1; i < ntypes; i++)
|
||||
for (int j = i+1; j <= ntypes; j++) {
|
||||
for (int j = i + 1; j <= ntypes; j++) {
|
||||
if (elements[i] == 0 || elements[j] == 0) continue;
|
||||
if (elements[i] == elements[j])
|
||||
error->all(FLERR,"MDI engine element cannot map to multiple types");
|
||||
error->all(FLERR, "MDI engine element cannot map to multiple types");
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,7 +168,7 @@ MDIEngine::MDIEngine(LAMMPS *_lmp, int narg, char ** arg) : Pointers(_lmp)
|
||||
ibuf1 = ibuf1all = nullptr;
|
||||
|
||||
maxatom = 0;
|
||||
sys_natoms = static_cast<int> (atom->natoms);
|
||||
sys_natoms = static_cast<int>(atom->natoms);
|
||||
reallocate();
|
||||
|
||||
nsteps = 0;
|
||||
@ -184,10 +185,10 @@ MDIEngine::MDIEngine(LAMMPS *_lmp, int narg, char ** arg) : Pointers(_lmp)
|
||||
|
||||
mdi_commands();
|
||||
|
||||
// register the execute_command function with MDI
|
||||
// only used when engine runs in plugin mode
|
||||
// register a callback function with MDI used when engine runs in plugin mode
|
||||
// execute_command_plugin_wrapper() must be a static method
|
||||
|
||||
MDI_Set_execute_command_func(lammps_execute_mdi_command, this);
|
||||
MDI_Set_execute_command_func(execute_command_plugin_wrapper, this);
|
||||
|
||||
// one-time operation to establish a connection with the driver
|
||||
|
||||
@ -291,11 +292,22 @@ void MDIEngine::engine_node(const char *node)
|
||||
node_match = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
wrapper function on execute_command()
|
||||
invoked as callback by MDI when engine operates in plugin mode
|
||||
this is a static method in mdi_engine.h
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
int MDIEngine::execute_command_plugin_wrapper(const char *command, MDI_Comm comm, void *class_obj)
|
||||
{
|
||||
auto mdi_engine = (MDIEngine *) class_obj;
|
||||
return mdi_engine->execute_command(command, comm);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
process a single driver command
|
||||
called by engine_node() in loop
|
||||
also called by MDI itself via lib::lammps_execute_mdi_command()
|
||||
when LAMMPS is running as a plugin
|
||||
called by engine_node() in loop when engine runs as stand-alone code
|
||||
called by execute_command_plugin_wrapper() when engine runs as plugin lib
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
@ -334,8 +346,7 @@ int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
receive_coords();
|
||||
|
||||
} else if (strcmp(command, ">ELEMENTS") == 0) {
|
||||
if (!elements)
|
||||
error->all(FLERR,"MDI engine command did not define element list");
|
||||
if (!elements) error->all(FLERR, "MDI engine command did not define element list");
|
||||
receive_elements();
|
||||
|
||||
} else if (strcmp(command, ">FORCES") == 0) {
|
||||
@ -362,7 +373,7 @@ int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
else
|
||||
receive_double3(VELOCITY);
|
||||
|
||||
// -----------------------------------------------
|
||||
// -----------------------------------------------
|
||||
|
||||
} else if (strcmp(command, "<@") == 0) {
|
||||
ierr = MDI_Send(node_engine, MDI_NAME_LENGTH, MDI_CHAR, mdicomm);
|
||||
@ -411,9 +422,9 @@ int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
} else if (strcmp(command, "<VELOCITIES") == 0) {
|
||||
send_double3(VELOCITY);
|
||||
|
||||
// -----------------------------------------------
|
||||
// -----------------------------------------------
|
||||
|
||||
// MDI action commands at @DEFAULT node
|
||||
// MDI action commands at @DEFAULT node
|
||||
|
||||
} else if (strcmp(command, "MD") == 0) {
|
||||
md();
|
||||
@ -421,9 +432,9 @@ int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
} else if (strcmp(command, "OPTG") == 0) {
|
||||
optg();
|
||||
|
||||
// -----------------------------------------------
|
||||
// -----------------------------------------------
|
||||
|
||||
// MDI node commands
|
||||
// MDI node commands
|
||||
|
||||
} else if (strcmp(command, "@INIT_MD") == 0) {
|
||||
if (mode != DEFAULT) error->all(FLERR, "MDI: MDI engine is already performing a simulation");
|
||||
@ -458,14 +469,14 @@ int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
strncpy(node_driver, command, MDI_COMMAND_LENGTH);
|
||||
node_match = false;
|
||||
|
||||
// exit command
|
||||
// exit command
|
||||
|
||||
} else if (strcmp(command, "EXIT") == 0) {
|
||||
exit_command = true;
|
||||
|
||||
// -------------------------------------------------------
|
||||
// custom LAMMPS commands
|
||||
// -------------------------------------------------------
|
||||
// -------------------------------------------------------
|
||||
// custom LAMMPS commands
|
||||
// -------------------------------------------------------
|
||||
|
||||
} else if (strcmp(command, "NBYTES") == 0) {
|
||||
nbytes_command();
|
||||
@ -478,9 +489,9 @@ int MDIEngine::execute_command(const char *command, MDI_Comm mdicomm)
|
||||
} else if (strcmp(command, "<KE") == 0) {
|
||||
send_ke();
|
||||
|
||||
// -------------------------------------------------------
|
||||
// unknown command
|
||||
// -------------------------------------------------------
|
||||
// -------------------------------------------------------
|
||||
// unknown command
|
||||
// -------------------------------------------------------
|
||||
|
||||
} else {
|
||||
error->all(FLERR, "MDI: Unknown command {} received from driver", command);
|
||||
@ -998,9 +1009,9 @@ void MDIEngine::create_system()
|
||||
// create list of 1 to sys_natoms IDs
|
||||
// optionally set charges if specified by ">CHARGES"
|
||||
|
||||
tagint* sys_ids;
|
||||
tagint *sys_ids;
|
||||
memory->create(sys_ids, sys_natoms, "mdi:sys_ids");
|
||||
for (int i = 0; i < sys_natoms; i++) sys_ids[i] = i+1;
|
||||
for (int i = 0; i < sys_natoms; i++) sys_ids[i] = i + 1;
|
||||
|
||||
if (flag_velocities)
|
||||
lammps_create_atoms(lmp, sys_natoms, sys_ids, sys_types, sys_coords, sys_velocities, nullptr,
|
||||
@ -1148,9 +1159,16 @@ void MDIEngine::receive_cell()
|
||||
for (int icell = 0; icell < 9; icell++) sys_cell[icell] *= mdi2lmp_length;
|
||||
|
||||
// error check that edge vectors match LAMMPS triclinic requirement
|
||||
// 3,7,6 = xy, yz, xz tilt factors
|
||||
|
||||
if (sys_cell[1] != 0.0 || sys_cell[2] != 0.0 || sys_cell[5] != 0.0)
|
||||
error->all(FLERR, "MDI: Received cell edges are not LAMMPS compatible");
|
||||
error->all(FLERR, "MDI: Received cell edges are not an upper triangular matrix");
|
||||
|
||||
if (sys_cell[3] != 0.0 || sys_cell[7] != 0.0 || sys_cell[6] != 0.0)
|
||||
if (!domain->triclinic)
|
||||
error->all(FLERR,
|
||||
"MDI: Received cell edges are for a triclinic box, "
|
||||
"but LAMMPS is using an orthogonal box");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -1227,8 +1245,7 @@ void MDIEngine::receive_elements()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itype > ntypes)
|
||||
error->all(FLERR,"MDI element not found in element list");
|
||||
if (itype > ntypes) error->all(FLERR, "MDI element not found in element list");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1493,6 +1510,9 @@ void MDIEngine::send_pe()
|
||||
/* ----------------------------------------------------------------------
|
||||
<STRESS command
|
||||
send 9-component stress tensor (no kinetic energy term)
|
||||
should be intensive quantity (divided by volume in pressure compute)
|
||||
MDI stress tensor units are energy/volume,
|
||||
so conversion factor includes nktv2p to convert pressure back to virial
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void MDIEngine::send_stress()
|
||||
@ -1837,6 +1857,8 @@ void MDIEngine::unit_conversions()
|
||||
}
|
||||
|
||||
// pressure or stress units = force/area = energy/volume
|
||||
// MDI energy/volume = Hartree/Bohr^3,
|
||||
// so need to remove LAMMPS nktv2p from pressure
|
||||
|
||||
mdi2lmp_pressure = 1.0;
|
||||
lmp2mdi_pressure = 1.0;
|
||||
|
||||
@ -22,8 +22,6 @@ namespace LAMMPS_NS {
|
||||
class MDIEngine : protected Pointers {
|
||||
public:
|
||||
MDIEngine(class LAMMPS *, int, char **);
|
||||
|
||||
int execute_command(const char *command, MDI_Comm mdicomm);
|
||||
void engine_node(const char *node);
|
||||
|
||||
private:
|
||||
@ -87,9 +85,13 @@ class MDIEngine : protected Pointers {
|
||||
class Irregular *irregular; // irregular comm if new COORDS
|
||||
// are highly displaced
|
||||
|
||||
// static method for MDI to callback to, when LAMMPS used as plugin engine
|
||||
|
||||
static int execute_command_plugin_wrapper(const char *, MDI_Comm, void *);
|
||||
|
||||
// class methods
|
||||
|
||||
void mdi_engine(int, char **);
|
||||
int execute_command(const char *, MDI_Comm);
|
||||
void mdi_commands();
|
||||
|
||||
void mdi_md();
|
||||
|
||||
@ -72,18 +72,23 @@ MDIPlugin::MDIPlugin(LAMMPS *_lmp, int narg, char **arg) : Pointers(_lmp)
|
||||
|
||||
// error checks
|
||||
|
||||
if (!mdi_arg || !infile_arg || !lammps_command)
|
||||
error->all(FLERR, "MDI plugin must specify mdi, infile, command keywords");
|
||||
if (!mdi_arg || !lammps_command)
|
||||
error->all(FLERR, "MDI plugin must specify mdi and command keywords");
|
||||
|
||||
// build full plugin_args string for args to plugin library
|
||||
|
||||
int n = strlen(mdi_arg) + strlen(infile_arg) + strlen(extra_arg) + 16;
|
||||
int n = strlen(mdi_arg) + 16;
|
||||
if (infile_arg) n += strlen(infile_arg);
|
||||
if (extra_arg) n += strlen(extra_arg);
|
||||
auto plugin_args = new char[n];
|
||||
plugin_args[0] = 0;
|
||||
strcat(plugin_args, "-mdi \"");
|
||||
strcat(plugin_args, mdi_arg);
|
||||
strcat(plugin_args, "\" -in ");
|
||||
strcat(plugin_args, infile_arg);
|
||||
strcat(plugin_args, "\"");
|
||||
if (infile_arg) {
|
||||
strcat(plugin_args, " -in ");
|
||||
strcat(plugin_args, infile_arg);
|
||||
}
|
||||
if (extra_arg) {
|
||||
strcat(plugin_args, " ");
|
||||
strcat(plugin_args, extra_arg);
|
||||
@ -91,7 +96,8 @@ MDIPlugin::MDIPlugin(LAMMPS *_lmp, int narg, char **arg) : Pointers(_lmp)
|
||||
|
||||
// launch the MDI plugin library
|
||||
// path for lib was specified in -mdi command-line arg when LAMMPS started
|
||||
// this calls back to plugin_wrapper, which must issue MDI EXIT at end
|
||||
// this calls back to plugin_wrapper(), which issues MDI EXIT at end & returns
|
||||
// plugin_wrapper() must be a static method
|
||||
|
||||
MDI_Launch_plugin(plugin_name, plugin_args, &world, plugin_wrapper, (void *) this);
|
||||
|
||||
@ -99,8 +105,9 @@ MDIPlugin::MDIPlugin(LAMMPS *_lmp, int narg, char **arg) : Pointers(_lmp)
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
callback function from MDI_Launch_plugin()
|
||||
this function wraps entire interaction of LAMMPS driver with the plugin
|
||||
wrapper on entire interaction of LAMMPS as a driver with the plugin engine
|
||||
invoked as a callback by MDI once plugin library engine is launched
|
||||
this is a static method in mdi_plugin.h
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
int MDIPlugin::plugin_wrapper(void * /*pmpicomm*/, MDI_Comm mdicomm, void *vptr)
|
||||
|
||||
@ -26,6 +26,9 @@ class MDIPlugin : protected Pointers {
|
||||
private:
|
||||
char *lammps_command;
|
||||
|
||||
// static method for MDI to callback to
|
||||
// when LAMMPS is a driver which launches a plugin engine
|
||||
|
||||
static int plugin_wrapper(void *, MDI_Comm, void *);
|
||||
};
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
#include "neigh_list.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -37,6 +38,7 @@ static constexpr double EPSILON = 1.0e-6;
|
||||
PairLJCutCoulCutDielectricOMP::PairLJCutCoulCutDielectricOMP(LAMMPS *_lmp) :
|
||||
PairLJCutCoulCutDielectric(_lmp), ThrOMP(_lmp, THR_PAIR)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -99,7 +101,7 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
{
|
||||
int i, j, ii, jj, jnum, itype, jtype;
|
||||
double qtmp, etmp, xtmp, ytmp, ztmp, delx, dely, delz, evdwl, ecoul;
|
||||
double fpair_i, fpair_j;
|
||||
double fpair_i;
|
||||
double rsq, r2inv, r6inv, forcecoul, forcelj, factor_coul, factor_lj;
|
||||
double efield_i, epot_i;
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
@ -130,10 +132,10 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
|
||||
i = ilist[ii];
|
||||
qtmp = q[i];
|
||||
etmp = eps[i];
|
||||
xtmp = x[i].x;
|
||||
ytmp = x[i].y;
|
||||
ztmp = x[i].z;
|
||||
etmp = eps[i];
|
||||
itype = type[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
@ -141,6 +143,7 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
extmp = eytmp = eztmp = 0.0;
|
||||
|
||||
// self term Eq. (55) for I_{ii} and Eq. (52) and in Barros et al
|
||||
|
||||
double curvature_threshold = sqrt(area[i]);
|
||||
if (curvature[i] < curvature_threshold) {
|
||||
double sf = curvature[i] / (4.0 * MY_PIS * curvature_threshold) * area[i] * q[i];
|
||||
@ -151,7 +154,7 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
efield[i][0] = efield[i][1] = efield[i][2] = 0;
|
||||
}
|
||||
|
||||
epot[i] = 0;
|
||||
epot[i] = 0.0;
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
@ -167,9 +170,10 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
|
||||
if (rsq < cutsq[itype][jtype]) {
|
||||
r2inv = 1.0 / rsq;
|
||||
const double rinv = sqrt(r2inv);
|
||||
|
||||
if (rsq < cut_coulsq[itype][jtype] && rsq > EPSILON) {
|
||||
efield_i = qqrd2e * q[j] * sqrt(r2inv);
|
||||
efield_i = qqrd2e * q[j] * rinv;
|
||||
forcecoul = qtmp * efield_i;
|
||||
epot_i = efield_i;
|
||||
} else
|
||||
@ -182,7 +186,6 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
forcelj = 0.0;
|
||||
|
||||
fpair_i = (factor_coul * etmp * forcecoul + factor_lj * forcelj) * r2inv;
|
||||
|
||||
fxtmp += delx * fpair_i;
|
||||
fytmp += dely * fpair_i;
|
||||
fztmp += delz * fpair_i;
|
||||
@ -193,29 +196,18 @@ void PairLJCutCoulCutDielectricOMP::eval(int iifrom, int iito, ThrData *const th
|
||||
eztmp += delz * efield_i;
|
||||
epot[i] += epot_i;
|
||||
|
||||
if (NEWTON_PAIR || j >= nlocal) {
|
||||
fpair_j = (factor_coul * eps[j] * forcecoul + factor_lj * forcelj) * r2inv;
|
||||
f[j].x -= delx * fpair_j;
|
||||
f[j].y -= dely * fpair_j;
|
||||
f[j].z -= delz * fpair_j;
|
||||
}
|
||||
|
||||
if (EFLAG) {
|
||||
if (rsq < cut_coulsq[itype][jtype]) {
|
||||
ecoul = factor_coul * qqrd2e * qtmp * q[j] * (etmp + eps[j]) * sqrt(r2inv);
|
||||
ecoul = factor_coul * qqrd2e * qtmp * q[j] * 0.5 * (etmp + eps[j]) * rinv;
|
||||
} else
|
||||
ecoul = 0.0;
|
||||
ecoul *= 0.5;
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
evdwl = r6inv * (lj3[itype][jtype] * r6inv - lj4[itype][jtype]) - offset[itype][jtype];
|
||||
evdwl *= factor_lj;
|
||||
} else
|
||||
evdwl = 0.0;
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this, i, j, nlocal, NEWTON_PAIR, evdwl, ecoul, fpair_i, delx, dely, delz,
|
||||
thr);
|
||||
if (EVFLAG) ev_tally_full_thr(this, i, evdwl, ecoul, fpair_i, delx, dely, delz, thr);
|
||||
}
|
||||
}
|
||||
f[i].x += fxtmp;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
#include "neigh_list.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -37,6 +38,7 @@ static constexpr double EPSILON = 1.0e-6;
|
||||
PairLJCutCoulDebyeDielectricOMP::PairLJCutCoulDebyeDielectricOMP(LAMMPS *_lmp) :
|
||||
PairLJCutCoulDebyeDielectric(_lmp), ThrOMP(_lmp, THR_PAIR)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -99,7 +101,7 @@ void PairLJCutCoulDebyeDielectricOMP::eval(int iifrom, int iito, ThrData *const
|
||||
{
|
||||
int i, j, ii, jj, jnum, itype, jtype;
|
||||
double qtmp, etmp, xtmp, ytmp, ztmp, delx, dely, delz, evdwl, ecoul;
|
||||
double fpair_i, fpair_j;
|
||||
double fpair_i;
|
||||
double rsq, r2inv, r6inv, forcecoul, forcelj, factor_coul, factor_lj, efield_i, epot_i;
|
||||
double r, rinv, screening;
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
@ -185,7 +187,6 @@ void PairLJCutCoulDebyeDielectricOMP::eval(int iifrom, int iito, ThrData *const
|
||||
forcelj = 0.0;
|
||||
|
||||
fpair_i = (factor_coul * etmp * forcecoul + factor_lj * forcelj) * r2inv;
|
||||
|
||||
fxtmp += delx * fpair_i;
|
||||
fytmp += dely * fpair_i;
|
||||
fztmp += delz * fpair_i;
|
||||
@ -196,19 +197,11 @@ void PairLJCutCoulDebyeDielectricOMP::eval(int iifrom, int iito, ThrData *const
|
||||
eztmp += delz * efield_i;
|
||||
epot[i] += epot_i;
|
||||
|
||||
if (NEWTON_PAIR || j >= nlocal) {
|
||||
fpair_j = (factor_coul * eps[j] * forcecoul + factor_lj * forcelj) * r2inv;
|
||||
f[j].x -= delx * fpair_j;
|
||||
f[j].y -= dely * fpair_j;
|
||||
f[j].z -= delz * fpair_j;
|
||||
}
|
||||
|
||||
if (EFLAG) {
|
||||
if (rsq < cut_coulsq[itype][jtype]) {
|
||||
ecoul = factor_coul * qqrd2e * qtmp * q[j] * (etmp + eps[j]) * rinv * screening;
|
||||
ecoul = factor_coul * qqrd2e * qtmp * q[j] * 0.5 * (etmp + eps[j]) * rinv * screening;
|
||||
} else
|
||||
ecoul = 0.0;
|
||||
ecoul *= 0.5;
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
evdwl = r6inv * (lj3[itype][jtype] * r6inv - lj4[itype][jtype]) - offset[itype][jtype];
|
||||
evdwl *= factor_lj;
|
||||
@ -216,9 +209,7 @@ void PairLJCutCoulDebyeDielectricOMP::eval(int iifrom, int iito, ThrData *const
|
||||
evdwl = 0.0;
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this, i, j, nlocal, NEWTON_PAIR, evdwl, ecoul, fpair_i, delx, dely, delz,
|
||||
thr);
|
||||
if (EVFLAG) ev_tally_full_thr(this, i, evdwl, ecoul, fpair_i, delx, dely, delz, thr);
|
||||
}
|
||||
}
|
||||
f[i].x += fxtmp;
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
#include "neigh_list.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -39,6 +40,7 @@ static constexpr double EPSILON = 1.0e-6;
|
||||
PairLJCutCoulLongDielectricOMP::PairLJCutCoulLongDielectricOMP(LAMMPS *_lmp) :
|
||||
PairLJCutCoulLongDielectric(_lmp), ThrOMP(_lmp, THR_PAIR)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -229,10 +231,10 @@ void PairLJCutCoulLongDielectricOMP::eval(int iifrom, int iito, ThrData *const t
|
||||
if (EFLAG) {
|
||||
if (rsq < cut_coulsq) {
|
||||
if (!ncoultablebits || rsq <= tabinnersq)
|
||||
ecoul = prefactor * (etmp + eps[j]) * erfc;
|
||||
ecoul = prefactor * 0.5 * (etmp + eps[j]) * erfc;
|
||||
else {
|
||||
table = etable[itable] + fraction * detable[itable];
|
||||
ecoul = qtmp * q[j] * (etmp + eps[j]) * table;
|
||||
ecoul = qtmp * q[j] * 0.5 * (etmp + eps[j]) * table;
|
||||
}
|
||||
if (factor_coul < 1.0) ecoul -= (1.0 - factor_coul) * prefactor;
|
||||
} else
|
||||
|
||||
@ -597,9 +597,8 @@ void ThrOMP::ev_tally_full_thr(Pair * const pair, const int i, const double evdw
|
||||
const double ecoul, const double fpair, const double delx,
|
||||
const double dely, const double delz, ThrData * const thr)
|
||||
{
|
||||
|
||||
if (pair->eflag_either)
|
||||
e_tally_thr(pair, i, i+1, i, 0, evdwl, ecoul, thr);
|
||||
e_tally_thr(pair, i, /*j*/ i+1, /*nlocal*/ i+1, /*newton_pair*/ 0, evdwl, ecoul, thr);
|
||||
|
||||
if (pair->vflag_either) {
|
||||
double v[6];
|
||||
@ -610,7 +609,7 @@ void ThrOMP::ev_tally_full_thr(Pair * const pair, const int i, const double evdw
|
||||
v[4] = delx*delz*fpair;
|
||||
v[5] = dely*delz*fpair;
|
||||
|
||||
v_tally_thr(pair, i, i+1, i, 0, v, thr);
|
||||
v_tally_thr(pair, i, /*j*/ i+1, /*nlocal*/ i+1, /*newton_pair*/ 0, v, thr);
|
||||
}
|
||||
|
||||
if (pair->num_tally_compute > 0) {
|
||||
|
||||
@ -1712,9 +1712,12 @@ void AtomVec::data_atom(double *coord, imageint imagetmp, const std::vector<std:
|
||||
|
||||
// error checks applicable to all styles
|
||||
|
||||
if (tag[nlocal] <= 0) error->one(FLERR, "Invalid atom ID in Atoms section of data file");
|
||||
if (tag[nlocal] <= 0)
|
||||
error->one(FLERR, "Invalid atom ID {} in line {} of Atoms section of data file",
|
||||
tag[nlocal], nlocal+1);
|
||||
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
|
||||
error->one(FLERR, "Invalid atom type in Atoms section of data file");
|
||||
error->one(FLERR, "Invalid atom type {} for atom {} in line {} of Atoms section of data file",
|
||||
type[nlocal], tag[nlocal], nlocal+1);
|
||||
|
||||
// if needed, modify unpacked values or initialize other peratom values
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ PairStyle(hybrid,PairHybrid);
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairHybrid : public Pair {
|
||||
friend class AtomVecDielectric;
|
||||
friend class ComputeSpin;
|
||||
friend class FixGPU;
|
||||
friend class FixIntel;
|
||||
|
||||
@ -559,6 +559,10 @@ std::string ReadRestart::file_search(const std::string &inpfile)
|
||||
bigint maxnum = -1;
|
||||
loc = pattern.find('*');
|
||||
if (loc != std::string::npos) {
|
||||
// the regex matcher in utils::strmatch() only checks the first 256 characters.
|
||||
if (loc > 256)
|
||||
error->one(FLERR, "Filename part before '*' is too long to find restart with largest step");
|
||||
|
||||
// convert pattern to equivalent regexp
|
||||
pattern.replace(loc,1,"\\d+");
|
||||
|
||||
|
||||
@ -1516,8 +1516,8 @@ static int re_matchp(const char *text, re_t pattern, int *matchlen);
|
||||
|
||||
/* Definitions: */
|
||||
|
||||
#define MAX_REGEXP_OBJECTS 30 /* Max number of regex symbols in expression. */
|
||||
#define MAX_CHAR_CLASS_LEN 40 /* Max length of character-class buffer in. */
|
||||
#define MAX_REGEXP_OBJECTS 256 /* Max number of regex symbols in expression. */
|
||||
#define MAX_CHAR_CLASS_LEN 256 /* Max length of character-class buffer in. */
|
||||
|
||||
enum {
|
||||
RX_UNUSED,
|
||||
|
||||
Reference in New Issue
Block a user