1D Langevin Thermostat

Hi Everyone,

I’m trying to modify the fix_langevin.cpp code to run it for some simulations where the only coordinate that is changing is “y” but I seem to be getting a higher temperature than the one I define. Has someone performed this before?

Thank you very much,

Sebastian Rodriguez

P.S.: This is the fix_langevin.cpp code that I have modified:

#include <mpi.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include “fix_langev1D.h”
#include “math_extra.h”
#include “atom.h”
#include “atom_vec_ellipsoid.h”
#include “force.h”
#include “update.h”
#include “modify.h”
#include “compute.h”
#include “domain.h”
#include “region.h”
#include “respa.h”
#include “comm.h”
#include “input.h”
#include “variable.h”
#include “random_mars.h”
#include “memory.h”
#include “error.h”
#include “group.h”

using namespace LAMMPS_NS;
using namespace FixConst;

enum{NOBIAS,BIAS};
enum{CONSTANT,EQUAL,ATOM};

#define SINERTIA 0.4 // moment of inertia prefactor for sphere
#define EINERTIA 0.2 // moment of inertia prefactor for ellipsoid

/* ---------------------------------------------------------------------- */

FixLangev1D::FixLangev1D(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (narg < 7) error->all(FLERR,“Illegal fix langev1D command”);

dynamic_group_allow = 1;
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
nevery = 1;

tstr = NULL;
if (strstr(arg[3],“v_”) == arg[3]) {
int n = strlen(&arg[3][2]) + 1;
tstr = new char[n];
strcpy(tstr,&arg[3][2]);
} else {
t_start = force->numeric(FLERR,arg[3]);
t_target = t_start;
tstyle = CONSTANT;
}

t_stop = force->numeric(FLERR,arg[4]);
t_period = force->numeric(FLERR,arg[5]);
seed = force->inumeric(FLERR,arg[6]);

if (t_period <= 0.0) error->all(FLERR,“Fix langev1D period must be > 0.0”);
if (seed <= 0) error->all(FLERR,“Illegal fix langev1D command”);

// initialize Marsaglia RNG with processor-unique seed

random = new RanMars(lmp,seed + comm->me);

// allocate per-type arrays for force prefactors

gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];
ratio = new double[atom->ntypes+1];

// optional args

for (int i = 1; i <= atom->ntypes; i++) ratio[i] = 1.0;
ascale = 0.0;
gjfflag = 0;
oflag = 0;
tallyflag = 0;
zeroflag = 0;

int iarg = 7;
while (iarg < narg) {
if (strcmp(arg[iarg],“angmom”) == 0) {
if (iarg+2 > narg) error->all(FLERR,“Illegal fix langev1D command”);
if (strcmp(arg[iarg+1],“no”) == 0) ascale = 0.0;
else ascale = force->numeric(FLERR,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],“gjf”) == 0) {
if (iarg+2 > narg) error->all(FLERR,“Illegal fix langev1D command”);
if (strcmp(arg[iarg+1],“no”) == 0) gjfflag = 0;
else if (strcmp(arg[iarg+1],“yes”) == 0) gjfflag = 1;
else error->all(FLERR,“Illegal fix langev1D command”);
iarg += 2;
} else if (strcmp(arg[iarg],“omega”) == 0) {
if (iarg+2 > narg) error->all(FLERR,“Illegal fix langev1D command”);
if (strcmp(arg[iarg+1],“no”) == 0) oflag = 0;
else if (strcmp(arg[iarg+1],“yes”) == 0) oflag = 1;
else error->all(FLERR,“Illegal fix langev1D command”);
iarg += 2;
} else if (strcmp(arg[iarg],“scale”) == 0) {
if (iarg+3 > narg) error->all(FLERR,“Illegal fix langev1D command”);
int itype = force->inumeric(FLERR,arg[iarg+1]);
double scale = force->numeric(FLERR,arg[iarg+2]);
if (itype <= 0 || itype > atom->ntypes)
error->all(FLERR,“Illegal fix langev1D command”);
ratio[itype] = scale;
iarg += 3;
} else if (strcmp(arg[iarg],“tally”) == 0) {
if (iarg+2 > narg) error->all(FLERR,“Illegal fix langev1D command”);
if (strcmp(arg[iarg+1],“no”) == 0) tallyflag = 0;
else if (strcmp(arg[iarg+1],“yes”) == 0) tallyflag = 1;
else error->all(FLERR,“Illegal fix langev1D command”);
iarg += 2;
} else if (strcmp(arg[iarg],“zero”) == 0) {
if (iarg+2 > narg) error->all(FLERR,“Illegal fix langev1D command”);
if (strcmp(arg[iarg+1],“no”) == 0) zeroflag = 0;
else if (strcmp(arg[iarg+1],“yes”) == 0) zeroflag = 1;
else error->all(FLERR,“Illegal fix langev1D command”);
iarg += 2;
} else error->all(FLERR,“Illegal fix langev1D command”);
}

// set temperature = NULL, user can override via fix_modify if wants bias

id_temp = NULL;
temperature = NULL;

// flangev1D is unallocated until first call to setup()
// compute_scalar checks for this and returns 0.0 if flangev1D is NULL

energy = 0.0;
flangev1D = NULL;
franprev = NULL;
tforce = NULL;
maxatom1 = maxatom2 = 0;

// Setup atom-based array for franprev
// register with Atom class
// No need to set peratom_flag
// as this data is for internal use only

if (gjfflag) {
nvalues = 3;
grow_arrays(atom->nmax);
atom->add_callback(0);

// initialize franprev to zero

int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
franprev[i][0] = 0.0;
franprev[i][1] = 0.0;
franprev[i][2] = 0.0;
}
}

if (tallyflag && zeroflag && comm->me == 0)
error->warning(FLERR,“Energy tally does not account for ‘zero yes’”);
}

/* ---------------------------------------------------------------------- */

FixLangev1D::~FixLangev1D()
{
delete random;
delete [] tstr;
delete [] gfactor1;
delete [] gfactor2;
delete [] ratio;
delete [] id_temp;
memory->destroy(flangev1D);
memory->destroy(tforce);

if (gjfflag) {
memory->destroy(franprev);
atom->delete_callback(id,0);
}
}

/* ---------------------------------------------------------------------- */

int FixLangev1D::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= END_OF_STEP;
mask |= THERMO_ENERGY;
return mask;
}

/* ---------------------------------------------------------------------- */

void FixLangev1D::init()
{
if (oflag && !atom->sphere_flag)
error->all(FLERR,“Fix langev1D omega requires atom style sphere”);
if (ascale && !atom->ellipsoid_flag)
error->all(FLERR,“Fix langev1D angmom requires atom style ellipsoid”);

// check variable

if (tstr) {
tvar = input->variable->find(tstr);
if (tvar < 0)
error->all(FLERR,“Variable name for fix langev1D does not exist”);
if (input->variable->equalstyle(tvar)) tstyle = EQUAL;
else if (input->variable->atomstyle(tvar)) tstyle = ATOM;
else error->all(FLERR,“Variable for fix langev1D is invalid style”);
}

// if oflag or ascale set, check that all group particles are finite-size

if (oflag) {
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;

for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0)
error->one(FLERR,“Fix langev1D omega requires extended particles”);
}

if (ascale) {
avec = (AtomVecEllipsoid *) atom->style_match(“ellipsoid”);
if (!avec)
error->all(FLERR,“Fix langev1D angmom requires atom style ellipsoid”);

int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;

for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (ellipsoid[i] < 0)
error->one(FLERR,“Fix langev1D angmom requires extended particles”);
}

// set force prefactors

if (!atom->rmass) {
for (int i = 1; i <= atom->ntypes; i++) {
gfactor1[i] = -atom->mass[i] / t_period / force->ftm2v;
gfactor2[i] = sqrt(atom->mass[i]) *
sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) /
force->ftm2v;
gfactor1[i] *= 1.0/ratio[i];
gfactor2[i] *= 1.0/sqrt(ratio[i]);
}
}

if (temperature && temperature->tempbias) tbiasflag = BIAS;
else tbiasflag = NOBIAS;

if (strstr(update->integrate_style,“respa”))
nlevels_respa = ((Respa *) update->integrate)->nlevels;

if (gjfflag) gjffac = 1.0/(1.0+update->dt/2.0/t_period);

}

/* ---------------------------------------------------------------------- */

void FixLangev1D::setup(int vflag)
{
if (strstr(update->integrate_style,“verlet”))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}

/* ---------------------------------------------------------------------- */

void FixLangev1D::post_force(int vflag)
{
double *rmass = atom->rmass;

// enumerate all 2^6 possibilities for template parameters
// this avoids testing them inside inner loop:
// TSTYLEATOM, GJF, TALLY, BIAS, RMASS, ZERO

#ifdef TEMPLATED_FIX_LANGEV1D
if (tstyle == ATOM)
if (gjfflag)
if (tallyflag)
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<1,1,1,1,1,1>();
else post_force_templated<1,1,1,1,1,0>();
else
if (zeroflag) post_force_templated<1,1,1,1,0,1>();
else post_force_templated<1,1,1,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<1,1,1,0,1,1>();
else post_force_templated<1,1,1,0,1,0>();
else
if (zeroflag) post_force_templated<1,1,1,0,0,1>();
else post_force_templated<1,1,1,0,0,0>();
else
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<1,1,0,1,1,1>();
else post_force_templated<1,1,0,1,1,0>();
else
if (zeroflag) post_force_templated<1,1,0,1,0,1>();
else post_force_templated<1,1,0,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<1,1,0,0,1,1>();
else post_force_templated<1,1,0,0,1,0>();
else
if (zeroflag) post_force_templated<1,1,0,0,0,1>();
else post_force_templated<1,1,0,0,0,0>();
else
if (tallyflag)
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<1,0,1,1,1,1>();
else post_force_templated<1,0,1,1,1,0>();
else
if (zeroflag) post_force_templated<1,0,1,1,0,1>();
else post_force_templated<1,0,1,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<1,0,1,0,1,1>();
else post_force_templated<1,0,1,0,1,0>();
else
if (zeroflag) post_force_templated<1,0,1,0,0,1>();
else post_force_templated<1,0,1,0,0,0>();
else
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<1,0,0,1,1,1>();
else post_force_templated<1,0,0,1,1,0>();
else
if (zeroflag) post_force_templated<1,0,0,1,0,1>();
else post_force_templated<1,0,0,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<1,0,0,0,1,1>();
else post_force_templated<1,0,0,0,1,0>();
else
if (zeroflag) post_force_templated<1,0,0,0,0,1>();
else post_force_templated<1,0,0,0,0,0>();
else
if (gjfflag)
if (tallyflag)
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<0,1,1,1,1,1>();
else post_force_templated<0,1,1,1,1,0>();
else
if (zeroflag) post_force_templated<0,1,1,1,0,1>();
else post_force_templated<0,1,1,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<0,1,1,0,1,1>();
else post_force_templated<0,1,1,0,1,0>();
else
if (zeroflag) post_force_templated<0,1,1,0,0,1>();
else post_force_templated<0,1,1,0,0,0>();
else
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<0,1,0,1,1,1>();
else post_force_templated<0,1,0,1,1,0>();
else
if (zeroflag) post_force_templated<0,1,0,1,0,1>();
else post_force_templated<0,1,0,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<0,1,0,0,1,1>();
else post_force_templated<0,1,0,0,1,0>();
else
if (zeroflag) post_force_templated<0,1,0,0,0,1>();
else post_force_templated<0,1,0,0,0,0>();
else
if (tallyflag)
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<0,0,1,1,1,1>();
else post_force_templated<0,0,1,1,1,0>();
else
if (zeroflag) post_force_templated<0,0,1,1,0,1>();
else post_force_templated<0,0,1,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<0,0,1,0,1,1>();
else post_force_templated<0,0,1,0,1,0>();
else
if (zeroflag) post_force_templated<0,0,1,0,0,1>();
else post_force_templated<0,0,1,0,0,0>();
else
if (tbiasflag == BIAS)
if (rmass)
if (zeroflag) post_force_templated<0,0,0,1,1,1>();
else post_force_templated<0,0,0,1,1,0>();
else
if (zeroflag) post_force_templated<0,0,0,1,0,1>();
else post_force_templated<0,0,0,1,0,0>();
else
if (rmass)
if (zeroflag) post_force_templated<0,0,0,0,1,1>();
else post_force_templated<0,0,0,0,1,0>();
else
if (zeroflag) post_force_templated<0,0,0,0,0,1>();
else post_force_templated<0,0,0,0,0,0>();
#else
post_force_untemplated(int(tstyle==ATOM), gjfflag, tallyflag,
int(tbiasflag==BIAS), int(rmass!=NULL), zeroflag);
#endif
}

/* ---------------------------------------------------------------------- */

void FixLangev1D::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}

/* ----------------------------------------------------------------------
modify forces using one of the many Langev1D styles
------------------------------------------------------------------------- */

#ifdef TEMPLATED_FIX_LANGEV1D
template < int Tp_TSTYLEATOM, int Tp_GJF, int Tp_TALLY,
int Tp_BIAS, int Tp_RMASS, int Tp_ZERO >
void FixLangev1D::post_force_templated()
#else
void FixLangev1D::post_force_untemplated
(int Tp_TSTYLEATOM, int Tp_GJF, int Tp_TALLY,
int Tp_BIAS, int Tp_RMASS, int Tp_ZERO)
#endif
{
double gamma1,gamma2;

double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;

// apply damping and thermostat to atoms in group

// for Tp_TSTYLEATOM:
// use per-atom per-coord target temperature
// for Tp_GJF:
// use Gronbech-Jensen/Farago algorithm
// else use regular algorithm
// for Tp_TALLY:
// store drag plus random forces in flangev1D[nlocal][3]
// for Tp_BIAS:
// calculate temperature since some computes require temp
// computed on current nlocal atoms to remove bias
// test v = 0 since some computes mask non-participating atoms via v = 0
// and added force has extra term not multiplied by v = 0
// for Tp_RMASS:
// use per-atom masses
// else use per-type masses
// for Tp_ZERO:
// sum random force over all atoms in group
// subtract sum/count from each atom in group

double fdrag[3],fran[3],fsum[3],fsumall[3];
bigint count;
double fswap;

double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;

compute_target();

if (Tp_ZERO) {
fsum[0] = fsum[1] = fsum[2] = 0.0;
count = group->count(igroup);
if (count == 0)
error->all(FLERR,“Cannot zero Langev1D force of 0 atoms”);
}

// reallocate flangev1D if necessary

if (Tp_TALLY) {
if (atom->nlocal > maxatom1) {
memory->destroy(flangev1D);
maxatom1 = atom->nmax;
memory->create(flangev1D,maxatom1,3,“langev1D:flangev1D”);
}
}

if (Tp_BIAS) temperature->compute_scalar();

for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (Tp_TSTYLEATOM) tsqrt = sqrt(tforce[i]);
if (Tp_RMASS) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
} else {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
}

fran[0] = 0;
fran[1] = 3gamma2(random->uniform()-0.5);
fran[2] = 0;

if (Tp_BIAS) {
temperature->remove_bias(i,v[i]);
fdrag[0] = 0;
fdrag[1] = 3gamma1v[i][1];
fdrag[2] = 0;
if (v[i][0] == 0.0) fran[0] = 0.0;
if (v[i][1] == 0.0) fran[1] = 0.0;
if (v[i][2] == 0.0) fran[2] = 0.0;
temperature->restore_bias(i,v[i]);
} else {
fdrag[0] = 0;
fdrag[1] = 3gamma1v[i][1];
fdrag[2] = 0;
}

if (Tp_GJF) {
fswap = 0;
franprev[i][0] = 0;
fran[0] = 0;
fswap = 0.5*(fran[1]+franprev[i][1]);
franprev[i][1] = fran[1];
fran[1] = fswap;
fswap = 0;
franprev[i][2] = 0;
fran[2] = 0;

fdrag[0] *= 0;
fdrag[1] = 3gjffac;
fdrag[2] *= 0;
fran[0] *= 0;
fran[1] = 3gjffac;
fran[2] *= 0;
f[i][0] *= 0;
f[i][1] = 3gjffac;
f[i][2] *= 0;
}

f[i][0] += 0;
f[i][1] += fdrag[1] + fran[1];
f[i][2] += 0;

if (Tp_TALLY) {
flangev1D[i][0] = 0;
flangev1D[i][1] = fdrag[1] + fran[1];
flangev1D[i][2] = 0;
}

if (Tp_ZERO) {
fsum[0] += 0;
fsum[1] += fran[1];
fsum[2] += 0;
}
}
}

// set total force to zero

if (Tp_ZERO) {
MPI_Allreduce(fsum,fsumall,3,MPI_DOUBLE,MPI_SUM,world);
fsumall[0] = 0;
fsumall[1] /= count;
fsumall[2] = 0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
f[i][0] -= 0;
f[i][1] -= fsumall[1];
f[i][2] -= 0;
}
}
}

// thermostat omega and angmom

if (oflag) omega_thermostat();
if (ascale) angmom_thermostat();
}

/* ----------------------------------------------------------------------
set current t_target and t_sqrt
------------------------------------------------------------------------- */

void FixLangev1D::compute_target()
{
int *mask = atom->mask;
int nlocal = atom->nlocal;

double delta = update->ntimestep - update->beginstep;
if (delta != 0.0) delta /= update->endstep - update->beginstep;

// if variable temp, evaluate variable, wrap with clear/add
// reallocate tforce array if necessary

if (tstyle == CONSTANT) {
t_target = t_start + delta * (t_stop-t_start);
tsqrt = sqrt(t_target);
} else {
modify->clearstep_compute();
if (tstyle == EQUAL) {
t_target = input->variable->compute_equal(tvar);
if (t_target < 0.0)
error->one(FLERR,“Fix langev1D variable returned negative temperature”);
tsqrt = sqrt(t_target);
} else {
if (nlocal > maxatom2) {
maxatom2 = atom->nmax;
memory->destroy(tforce);
memory->create(tforce,maxatom2,“langev1D:tforce”);
}
input->variable->compute_atom(tvar,igroup,tforce,1,0);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (tforce[i] < 0.0)
error->one(FLERR,
“Fix langev1D variable returned negative temperature”);
}
modify->addstep_compute(update->ntimestep + 1);
}
}

/* ----------------------------------------------------------------------
thermostat rotational dof via omega
------------------------------------------------------------------------- */

void FixLangev1D::omega_thermostat()
{
double gamma1,gamma2;

double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;

double **torque = atom->torque;
double **omega = atom->omega;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;

// rescale gamma1/gamma2 by 10/3 & sqrt(10/3) for spherical particles
// does not affect rotational thermosatting
// gives correct rotational diffusivity behavior

double tendivthree = 10.0/3.0;
double tran[3];
double inertiaone;

for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && (radius[i] > 0.0)) {
inertiaone = SINERTIA*radius[i]radius[i]rmass[i];
if (tstyle == ATOM) tsqrt = sqrt(tforce[i]);
gamma1 = -tendivthree
inertiaone / t_period / ftm2v;
gamma2 = sqrt(inertiaone) * sqrt(80.0
boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 = 1.0/ratio[type[i]];
gamma2 = 1.0/sqrt(ratio[type[i]]) * tsqrt;
tran[0] = 0;
tran[1] = gamma2
(random->uniform()-0.5);
tran[2] = 0;
torque[i][0] += 0;
torque[i][1] += gamma1
omega[i][1] + tran[1];
torque[i][2] += 0;
}
}
}

/* ----------------------------------------------------------------------
thermostat rotational dof via angmom
------------------------------------------------------------------------- */

void FixLangev1D::angmom_thermostat()
{
double gamma1,gamma2;

double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;

AtomVecEllipsoid::Bonus *bonus = avec->bonus;
double **torque = atom->torque;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;

// rescale gamma1/gamma2 by ascale for aspherical particles
// does not affect rotational thermosatting
// gives correct rotational diffusivity behavior if (nearly) spherical
// any value will be incorrect for rotational diffusivity if aspherical

double inertia[3],omega[3],tran[3];
double *shape,*quat;

for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
shape = bonus[ellipsoid[i]].shape;
inertia[0] = 0;
inertia[1] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = 0;
quat = bonus[ellipsoid[i]].quat;
MathExtra::mq_to_omega(angmom[i],quat,inertia,omega);

if (tstyle == ATOM) tsqrt = sqrt(tforce[i]);
gamma1 = -ascale / t_period / ftm2v;
gamma2 = sqrt(ascale24.0boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
tran[0] = 0;
tran[1] = sqrt(inertia[1])gamma2(random->uniform()-0.5);
tran[2] = 0;
torque[i][0] += 0;
torque[i][1] += inertia[1]gamma1omega[1] + tran[1];
torque[i][2] += 0;
}
}
}

/* ----------------------------------------------------------------------
tally energy transfer to thermal reservoir
------------------------------------------------------------------------- */

void FixLangev1D::end_of_step()
{
if (!tallyflag) return;

double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;

energy_onestep = 0.0;

for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
energy_onestep += flangev1D[i][1]*v[i][1];

energy += energy_onestep*update->dt;
}

/* ---------------------------------------------------------------------- */

void FixLangev1D::reset_target(double t_new)
{
t_target = t_start = t_stop = t_new;
}

/* ---------------------------------------------------------------------- */

void FixLangev1D::reset_dt()
{
if (atom->mass) {
for (int i = 1; i <= atom->ntypes; i++) {
gfactor2[i] = sqrt(atom->mass[i]) *
sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) /
force->ftm2v;
gfactor2[i] *= 1.0/sqrt(ratio[i]);
}
}
}

/* ---------------------------------------------------------------------- */

int FixLangev1D::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],“temp”) == 0) {
if (narg < 2) error->all(FLERR,“Illegal fix_modify command”);
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);

int icompute = modify->find_compute(id_temp);
if (icompute < 0)
error->all(FLERR,“Could not find fix_modify temperature ID”);
temperature = modify->compute[icompute];

if (temperature->tempflag == 0)
error->all(FLERR,
“Fix_modify temperature ID does not compute temperature”);
if (temperature->igroup != igroup && comm->me == 0)
error->warning(FLERR,“Group for fix_modify temp != fix group”);
return 2;
}
return 0;
}

/* ---------------------------------------------------------------------- */

double FixLangev1D::compute_scalar()
{
if (!tallyflag || flangev1D == NULL) return 0.0;

// capture the very first energy transfer to thermal reservoir

double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;

if (update->ntimestep == update->beginstep) {
energy_onestep = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
energy_onestep += flangev1D[i][1]v[i][1];
energy = 0.5
energy_onestep*update->dt;
}

// convert midstep energy back to previous fullstep energy

double energy_me = energy - 0.5energy_onestepupdate->dt;

double energy_all;
MPI_Allreduce(&energy_me,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
return -energy_all;
}

/* ----------------------------------------------------------------------
extract thermostat properties
------------------------------------------------------------------------- */

void *FixLangev1D::extract(const char *str, int &dim)
{
dim = 0;
if (strcmp(str,“t_target”) == 0) {
return &t_target;
}
return NULL;
}

/* ----------------------------------------------------------------------
memory usage of tally array
------------------------------------------------------------------------- */

double FixLangev1D::memory_usage()
{
double bytes = 0.0;
if (gjfflag) bytes += atom->nmax3 * sizeof(double);
if (tallyflag) bytes += atom->nmax
3 * sizeof(double);
if (tforce) bytes += atom->nmax * sizeof(double);
return bytes;
}

/* ----------------------------------------------------------------------
allocate atom-based array for franprev
------------------------------------------------------------------------- */

void FixLangev1D::grow_arrays(int nmax)
{
memory->grow(franprev,nmax,3,“fix_langev1D:franprev”);
}

/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */

void FixLangev1D::copy_arrays(int i, int j, int delflag)
{
for (int m = 0; m < nvalues; m++)
franprev[j][m] = franprev[i][m];
}

/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */

int FixLangev1D::pack_exchange(int i, double *buf)
{
for (int m = 0; m < nvalues; m++) buf[m] = franprev[i][m];
return nvalues;
}

/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */

int FixLangev1D::unpack_exchange(int nlocal, double *buf)
{
for (int m = 0; m < nvalues; m++) franprev[nlocal][m] = buf[m];
return nvalues;
}

Hi Everyone,

I'm trying to modify the fix_langevin.cpp code to run it for some
simulations where the only coordinate that is changing is "y" but I seem to
be getting a higher temperature than the one I define. Has someone performed
this before?

why modify the source? you should be able to have a 1-d thermostat by
subtracting a bias as explained here:
http://lammps.sandia.gov/doc/Section_howto.html#howto-16

axel.

Hi Axel,

thanks for your reply! I think I tried that before:

Calculating the different components of the non-bonded energy

compute 1 all bond/local dist eng
compute newtemp all temp/partial 0 1 0

Specifying the frequency of thermodynamic output

thermo 100
thermo_style custom step ebond temp

Specifying a Langevin integrator to perform a simulation in the NVT ensemble

fix 1 realatom1 langevin {T} {T} 5000 ${random} gjf yes
fix 2 realatom1 nve
fix 3 realatom1 setforce 0.0 NULL 0.0
fix 4 fixatom1 setforce 0.0 0.0 0.0
fix 5 boundaries setforce 0.0 0.0 0.0
fix_modify 1 temp newtemp

But it gave me much lower temperature values. Am I doing something wrong?

Hi Axel,

thanks for your reply! I think I tried that before:

# Calculating the different components of the non-bonded energy
compute 1 all bond/local dist eng
compute newtemp all temp/partial 0 1 0

# Specifying the frequency of thermodynamic output
thermo 100
thermo_style custom step ebond temp

# Specifying a Langevin integrator to perform a simulation in the NVT
ensemble
fix 1 realatom1 langevin \{T\} {T} 5000 ${random} gjf yes
fix 2 realatom1 nve
fix 3 realatom1 setforce 0.0 NULL 0.0
fix 4 fixatom1 setforce 0.0 0.0 0.0
fix 5 boundaries setforce 0.0 0.0 0.0
fix_modify 1 temp newtemp

But it gave me much lower temperature values. Am I doing something wrong?

difficult to say from an incomplete input deck. but it does seem
strange to me that you start modifying code without first having
understood what the origin of the lower than expected temperature is.
i would rather construct a set of simpler inputs and manually compare
the temperature computed by lammps with that you compute yourself from
dumping velocities. if you start from something that works and
gradually transform to the system you want to study, it should be
straightforward to pinpoint the step that causes problems and then
you'd perhaps see where your problem is or if there is something in
LAMMPS that is not working as documented.

axel.

Thanks for your reply Axel! This is my current input. I think I have problems either with having fixed

atoms or with having movement only in the y direction (probably both)

Test system for LAMMPS simulation

units real
atom_style full
log sim273.log

For a single processor calculation

variable T equal 273 # Simulation temperature
variable salt equal 100.0 # Salt concentration [mM]

Random number seed for Langevin integrator

variable random equal 12345

Specify the different interaction styles

bond_style hybrid morse potential1
angle_style none
dihedral_style none
pair_style none

Periodic boundary conditions

boundary p p p

Turn on Newton’s 2nd law

newton on #yes

Read in the configuration

read_data bdna_conf.in

Specify parameters for the neighbor list

neighbor 4.0 multi
neigh_modify check no
atom_modify sort 0 0.0

A timestep of 0.10 ps

timestep 100

Define the groups of the real atoms and their fix initial positions

group realatom1 id 2:10 24:32 46:54 68:76 90:98 112:120 134:142 156:164 178:186 200:208 222:230 244:252 266:274 288:296 310:318 332:340 354:362 376:384 398:406 420:428 442:450 464:472 486:494 508:516 530:538 552:560 574:582 596:604 618:626 640:648 662:670 684:692 706:714 728:736 750:758 772:780 794:802 816:824 838:846 860:868 882:890 904:912 926:934 948:956 970:978 992:1000 1014:1022 1036:1044 1058:1066 1080:1088 1102:1110 1124:1132 1146:1154 1168:1176 1190:1198 1212:1220 1234:1242 1256:1264 1278:1286 1300:1308 1322:1330 1344:1352 1366:1374 1388:1396 1410:1418 1432:1440 1454:1462 1476:1484 1498:1506 1520:1528 1542:1550 1564:1572 1586:1594 1608:1616 1630:1638 1652:1660 1674:1682 1696:1704 1718:1726 1740:1748 1762:1770 1784:1792 1806:1814 1828:1836 1850:1858 1872:1880 1894:1902 1916:1924 1938:1946 1960:1968 1982:1990 2004:2012 2026:2034 2048:2056 2070:2078 2092:2100 2114:2122 2136:2144 2158:2166 2180:2188 2202:2210 2224:2232 2246:2254 2268:2276 2290:2298 2312:2320 2334:2342 2356:2364 2378:2386 2400:2408 2422:2430 2444:2452 2466:2474 2488:2496 2510:2518 2532:2540 2554:2562 2576:2584 2598:2606 2620:2628 2642:2650 2664:2672 2686:2694 2708:2716 2730:2738 2752:2760 2774:2782 2796:2804 2818:2826 2840:2848 2862:2870 2884:2892 2906:2914 2928:2936 2950:2958 2972:2980 2994:3002 3016:3024 3038:3046 3060:3068 3082:3090 3104:3112 3126:3134 3148:3156 3170:3178 3192:3200 3214:3222 3236:3244 3258:3266 3280:3288 3302:3310 3324:3332 3346:3354 3368:3376 3390:3398 3412:3420 3434:3442 3456:3464 3478:3486 3500:3508 3522:3530
group fixatom1 type 5
group boundaries id 1 11 23 33 45 55 67 77 89 99 111 121 133 143 155 165 177 187 199 209 221 231 243 253 265 275 287 297 309 319 331 341 353 363 375 385 397 407 419 429 441 451 463 473 485 495 507 517 529 539 551 561 573 583 595 605 617 627 639 649 661 671 683 693 705 715 727 737 749 759 771 781 793 803 815 825 837 847 859 869 881 891 903 913 925 935 947 957 969 979 991 1001 1013 1023 1035 1045 1057 1067 1079 1089 1101 1111 1123 1133 1145 1155 1167 1177 1189 1199 1211 1221 1233 1243 1255 1265 1277 1287 1299 1309 1321 1331 1343 1353 1365 1375 1387 1397 1409 1419 1431 1441 1453 1463 1475 1485 1497 1507 1519 1529 1541 1551 1563 1573 1585 1595 1607 1617 1629 1639 1651 1661 1673 1683 1695 1705 1717 1727 1739 1749 1761 1771 1783 1793 1805 1815 1827 1837 1849 1859 1871 1881 1893 1903 1915 1925 1937 1947 1959 1969 1981 1991 2003 2013 2025 2035 2047 2057 2069 2079 2091 2101 2113 2123 2135 2145 2157 2167 2179 2189 2201 2211 2223 2233 2245 2255 2267 2277 2289 2299 2311 2321 2333 2343 2355 2365 2377 2387 2399 2409 2421 2431 2443 2453 2465 2475 2487 2497 2509 2519 2531 2541 2553 2563 2575 2585 2597 2607 2619 2629 2641 2651 2663 2673 2685 2695 2707 2717 2729 2739 2751 2761 2773 2783 2795 2805 2817 2827 2839 2849 2861 2871 2883 2893 2905 2915 2927 2937 2949 2959 2971 2981 2993 3003 3015 3025 3037 3047 3059 3069 3081 3091 3103 3113 3125 3135 3147 3157 3169 3179 3191 3201 3213 3223 3235 3245 3257 3267 3279 3289 3301 3311 3323 3333 3345 3355 3367 3377 3389 3399 3411 3421 3433 3443 3455 3465 3477 3487 3499 3509 3521 3531
group mobile union realatom1 boundaries

Initialize velocities from a Gaussian distribution

velocity mobile create {T} {random} rot yes mom yes dist gaussian
velocity mobile set 0.0 NULL 0.0
velocity fixatom1 set 0.0 0.0 0.0
run 0
velocity all scale ${T}

Calculating the different components of the non-bonded energy

compute 1 all bond/local dist eng
compute newtemp mobile temp/partial 0 1 0

Specifying the frequency of thermodynamic output

thermo 500
thermo_style custom step ebond temp

Specifying a Langevin integrator to perform a simulation in the NVT ensemble

fix 3 mobile langevin {T} {T} 5000 ${random} gjf yes
fix 4 mobile nve
fix 5 mobile setforce 0.0 NULL 0.0
fix 6 fixatom1 setforce 0.0 0.0 0.0
fix_modify 3 temp newtemp

Write configuration to file

dump 1 mobile custom 500 traj273.xyz x y z vy

Run X number of steps

run 30000

It seems like it gets fixed by changing

thermo_style custom step ebond temp

by

thermo_style custom step ebond c_newtemp

Although I still have to run some other simulations to see if that really fixed everything

There still seems to be something odd with the thermostat. This is my current input, and I’m getting way lower displacements than I expected…

Test system for LAMMPS simulation

units real
atom_style full
log sim323.log

For a single processor calculation

variable T equal 423 # Simulation temperature
variable salt equal 100.0 # Salt concentration [mM]

Random number seed for Langevin integrator

variable random equal 12345

Specify the different interaction styles

bond_style hybrid morse potential1
angle_style none
dihedral_style none
pair_style none

Periodic boundary conditions

boundary p p p

Turn on Newton’s 2nd law

newton on #yes

Read in the configuration

read_data bdna_conf.in

Specify parameters for the neighbor list

neighbor 4.0 multi
neigh_modify check no
atom_modify sort 0 0.0

A timestep of 0.10 ps

timestep 100

Define the groups of the real atoms and their fix initial positions

group realatom1 id 2:10 24:32 46:54 68:76 90:98 112:120 134:142 156:164 178:186 200:208 222:230 244:252 266:274 288:296 310:318 332:340 354:362 376:384 398:406 420:428 442:450 464:472 486:494 508:516 530:538 552:560 574:582 596:604 618:626 640:648 662:670 684:692 706:714 728:736 750:758 772:780 794:802 816:824 838:846 860:868 882:890 904:912 926:934 948:956 970:978 992:1000 1014:1022 1036:1044 1058:1066 1080:1088 1102:1110 1124:1132 1146:1154 1168:1176 1190:1198 1212:1220 1234:1242 1256:1264 1278:1286 1300:1308 1322:1330 1344:1352 1366:1374 1388:1396 1410:1418 1432:1440 1454:1462 1476:1484 1498:1506 1520:1528 1542:1550 1564:1572 1586:1594 1608:1616 1630:1638 1652:1660 1674:1682 1696:1704 1718:1726 1740:1748 1762:1770 1784:1792 1806:1814 1828:1836 1850:1858 1872:1880 1894:1902 1916:1924 1938:1946 1960:1968 1982:1990 2004:2012 2026:2034 2048:2056 2070:2078 2092:2100 2114:2122 2136:2144 2158:2166 2180:2188 2202:2210 2224:2232 2246:2254 2268:2276 2290:2298 2312:2320 2334:2342 2356:2364 2378:2386 2400:2408 2422:2430 2444:2452 2466:2474 2488:2496 2510:2518 2532:2540 2554:2562 2576:2584 2598:2606 2620:2628 2642:2650 2664:2672 2686:2694 2708:2716 2730:2738 2752:2760 2774:2782 2796:2804 2818:2826 2840:2848 2862:2870 2884:2892 2906:2914 2928:2936 2950:2958 2972:2980 2994:3002 3016:3024 3038:3046 3060:3068 3082:3090 3104:3112 3126:3134 3148:3156 3170:3178 3192:3200 3214:3222 3236:3244 3258:3266 3280:3288 3302:3310 3324:3332 3346:3354 3368:3376 3390:3398 3412:3420 3434:3442 3456:3464 3478:3486 3500:3508 3522:3530
group fixatom1 type 5
group boundaries id 1 11 23 33 45 55 67 77 89 99 111 121 133 143 155 165 177 187 199 209 221 231 243 253 265 275 287 297 309 319 331 341 353 363 375 385 397 407 419 429 441 451 463 473 485 495 507 517 529 539 551 561 573 583 595 605 617 627 639 649 661 671 683 693 705 715 727 737 749 759 771 781 793 803 815 825 837 847 859 869 881 891 903 913 925 935 947 957 969 979 991 1001 1013 1023 1035 1045 1057 1067 1079 1089 1101 1111 1123 1133 1145 1155 1167 1177 1189 1199 1211 1221 1233 1243 1255 1265 1277 1287 1299 1309 1321 1331 1343 1353 1365 1375 1387 1397 1409 1419 1431 1441 1453 1463 1475 1485 1497 1507 1519 1529 1541 1551 1563 1573 1585 1595 1607 1617 1629 1639 1651 1661 1673 1683 1695 1705 1717 1727 1739 1749 1761 1771 1783 1793 1805 1815 1827 1837 1849 1859 1871 1881 1893 1903 1915 1925 1937 1947 1959 1969 1981 1991 2003 2013 2025 2035 2047 2057 2069 2079 2091 2101 2113 2123 2135 2145 2157 2167 2179 2189 2201 2211 2223 2233 2245 2255 2267 2277 2289 2299 2311 2321 2333 2343 2355 2365 2377 2387 2399 2409 2421 2431 2443 2453 2465 2475 2487 2497 2509 2519 2531 2541 2553 2563 2575 2585 2597 2607 2619 2629 2641 2651 2663 2673 2685 2695 2707 2717 2729 2739 2751 2761 2773 2783 2795 2805 2817 2827 2839 2849 2861 2871 2883 2893 2905 2915 2927 2937 2949 2959 2971 2981 2993 3003 3015 3025 3037 3047 3059 3069 3081 3091 3103 3113 3125 3135 3147 3157 3169 3179 3191 3201 3213 3223 3235 3245 3257 3267 3279 3289 3301 3311 3323 3333 3345 3355 3367 3377 3389 3399 3411 3421 3433 3443 3455 3465 3477 3487 3499 3509 3521 3531
group mobile union realatom1 boundaries

Initialize velocities from a Gaussian distribution

velocity mobile create {T} {random} rot yes mom yes dist gaussian
velocity mobile set 0.0 NULL 0.0
velocity fixatom1 set 0.0 0.0 0.0
run 0
velocity all scale ${T}

Calculating the different components of the non-bonded energy

compute 1 all bond/local dist eng
compute newtemp mobile temp/partial 0 1 0

Specifying the frequency of thermodynamic output

thermo 500
thermo_style custom step ebond etotal c_newtemp

Specifying a Langevin integrator to perform a simulation in the NVT ensemble

fix 3 mobile langevin {T} {T} 5000 ${random} gjf yes
fix 4 mobile nve
fix 5 mobile setforce 0.0 NULL 0.0
fix 6 fixatom1 setforce 0.0 0.0 0.0

Write configuration to file

dump 1 mobile custom 500 traj323.xyz x y z vy
dump 2 all xyz 500 traj323b.xyz

Run X number of steps

run 30000

I believe it is either working at 3D and then making the x and z coordinates null, or having problems with the fixed atoms and therefore working at a lower temperature than it should

Sebastian,

You seem to be flailing around. Your original question in the previous thread (and also this new one that you seem to have started in parallel) was about temperature. Ray Shan pointed out that you were outputting the wrong temperature compute. This is a fairly basic mistake that you made. Yet you are still insisting that there must be something wrong with LAMMPS. Your new evidence has something to do with your expectations for “displacements.” I think your time would be better spent familiarizing yourself with the LAMMPS documentation.

Aidan

Hi Aidan,

thanks! Yep, I’m having problems understanding the thermostat. I will analyze the cpp code and start from there

Hi Aidan,

thanks! Yep, I'm having problems understanding the thermostat. I will
analyze the cpp code and start from there

that is a *bad* idea. the fix langevin source code is quite complex
and considering your general struggles with basic concepts, it will
likely be more confusing than helpful. i strongly encourage you to do
as aidan suggests and start with the documentation. read *all* of the
relevant files and check the cross references. then build *simple*(!!)
test examples where you introduce items like immobilized atoms or
dimension biased thermostats and so on individually and compare the
output for each with your expectations. ...and use a simpler to follow
thermostat code, in case you insist on reading the source. the
principles are the same. but "bad" thermostats like temp/rescale or
temp/berendsen are (still) popular because they are easy to grasp and
to implement (they are still very bad, tho, for serious production
runs).

in other words, thy applying a little common sense instead of
producing hectic and not well guided activity.

axel.