git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@13681 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
56
src/USER-QTB/README
Normal file
56
src/USER-QTB/README
Normal file
@ -0,0 +1,56 @@
|
||||
This package contains 2 fix commands, "fix qtb" and
|
||||
"fix qbmsst" which involve quantum nuclear effects.
|
||||
|
||||
What is quantum nuclear effects (in molecular dynamics
|
||||
simulation)?
|
||||
Quantum treatment of the vibrational modes will
|
||||
introduce zero point energy into the system, alter
|
||||
the energy power spectrum and bias the heat capacity
|
||||
from the classical limit. classical MD leaves out
|
||||
these effects completely and thus need to be corrected.
|
||||
|
||||
When should I consider quantum nuclear effects in
|
||||
my simulation?
|
||||
(1) When you want to model systems at temperatures
|
||||
lower than their classical limits. This is especially
|
||||
important for materials with a large population of
|
||||
hydrogen atoms and thus higher classical limits.
|
||||
|
||||
(2) In MD simulations when temperatures ramp up
|
||||
across (or starting from somewhere close to) the
|
||||
classical limits, tiny differences between the
|
||||
classical and quantum heat capacity can accumulate
|
||||
and cause the final state to deviate (could be as
|
||||
large as 30 %).
|
||||
|
||||
What command should I use regarding these two cases?
|
||||
(1) "fix qtb" provides quantum nulcear correction
|
||||
through a colored thermostat and can be used with
|
||||
other time integration schemes like fix nve or
|
||||
fix nph. In this case, you tell "fix qtb" the temperature
|
||||
and the other time integration scheme either the
|
||||
pressure ("fix nph") or the volume ("fix nve").
|
||||
|
||||
(2) "fix qbmsst" deals with shock MD simulations
|
||||
in which cases the temperature may increase a lot.
|
||||
It enables quantum nuclear correction of a multi-scale
|
||||
shock technique simulation by coupling the quantum
|
||||
thermal bath with the shocked system. It is an independent
|
||||
command from "fix msst" and does not assume that
|
||||
the SHOCK package has been installed.
|
||||
|
||||
See the doc page for the fix qtb and fix qbmsst
|
||||
command for detailed usage instructions.
|
||||
|
||||
Where can I find examples of these two commands?
|
||||
There are example scripts for using this package in
|
||||
examples/USER/qtb, including one "fix qtb" and one
|
||||
"fix qbmsst" example for each of alpha quartz and
|
||||
methane. Running the alpha quartz example requires
|
||||
installation of the kspace package while the methane
|
||||
example requires the REAX package for the force field.
|
||||
|
||||
Authors Information and Contact
|
||||
The person who created this package is Yuan Shen
|
||||
(sy0302 at stanford.edu) at Stanford University.
|
||||
Contact him directly if you have questions.
|
||||
1195
src/USER-QTB/fix_qbmsst.cpp
Normal file
1195
src/USER-QTB/fix_qbmsst.cpp
Normal file
File diff suppressed because it is too large
Load Diff
124
src/USER-QTB/fix_qbmsst.h
Normal file
124
src/USER-QTB/fix_qbmsst.h
Normal file
@ -0,0 +1,124 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Shen,Yuan, Qi,Tingting, and Reed,Evan
|
||||
Implementation of the Multi-Scale Shock Method with quantum nuclear effects
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
|
||||
FixStyle(qbmsst,FixQBMSST)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef FIX_QBMSST_H
|
||||
#define FIX_QBMSST_H
|
||||
|
||||
#include "fix.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixQBMSST : public Fix {
|
||||
public:
|
||||
FixQBMSST(class LAMMPS *, int, char **);
|
||||
~FixQBMSST();
|
||||
int setmask();
|
||||
void init();
|
||||
void setup(int);
|
||||
void initial_integrate(int);
|
||||
void final_integrate();
|
||||
double compute_scalar();
|
||||
double compute_vector(int);
|
||||
void write_restart(FILE *);
|
||||
void restart(char *);
|
||||
int modify_param(int, char **);
|
||||
double memory_usage();
|
||||
void grow_arrays(int);
|
||||
void copy_arrays(int, int, int);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(int, double *);
|
||||
|
||||
private:
|
||||
// msst parameters
|
||||
int direction; // Direction of shock
|
||||
double velocity; // Velocity of the shock
|
||||
double qmass; // Effective cell mass
|
||||
double mu; // Effective cell viscosity
|
||||
double e0; // Initial energy
|
||||
double v0; // Initial volume
|
||||
double p0; // Initial pressure
|
||||
int p0_set; // Is pressure set
|
||||
int v0_set; // Is volume set
|
||||
int e0_set; // Is energy set
|
||||
double tscale; // Converts thermal energy to compressive strain ke at simulation start
|
||||
char *id_temp,*id_press, *id_pe; // Strings with identifiers of created computes.
|
||||
int tflag,pflag,vsflag,peflag; // Flags to keep track of computes that were created.
|
||||
double dtv; // update->dt
|
||||
double dtf; // Full step size
|
||||
double dthalf; // half step size
|
||||
bigint ntotal; // atom->natoms
|
||||
double boltz,nktv2p, mvv2e; // Boltzmann factor and unit conversions
|
||||
class Compute *temperature; // Computes created to evaluate
|
||||
class Compute *pressure; // thermodynamic quantities.
|
||||
class Compute *pe;
|
||||
double **old_velocity; // Saved velocities.
|
||||
int atoms_allocated; // size of old_velocity
|
||||
double dilation[3];
|
||||
double omega[3]; // Time derivative of the volume.
|
||||
double total_mass; // Mass of the computational cell
|
||||
int kspace_flag; // 1 if KSpace invoked, 0 if not
|
||||
int nrigid; // number of rigid fixes
|
||||
int *rfix; // indices of rigid fixes
|
||||
double p_current[3]; // pressure
|
||||
double velocity_sum; // Sum of the velocities squared.
|
||||
double lagrangian_position; // Lagrangian location of computational cell
|
||||
|
||||
// qbmsst parameters
|
||||
double t_period, fric_coef; // friction coefficient
|
||||
int seed; // seed for the random number generator
|
||||
double f_max; // frequency cutoff
|
||||
int N_f; // number of frequency grid
|
||||
double eta; // coupling coefficient bewteen shock and the qtb
|
||||
int beta; // average beta steps before updating the qtb temperature
|
||||
double t_init; // initial qtb temperature
|
||||
int qtb_set; // 1 if its a restarting qbmsst, 0 if not
|
||||
int counter_l, counter_mu; // counter l and mu
|
||||
double t_current; // qtb temperature
|
||||
double h_timestep; // time step to update the random forces
|
||||
int alpha; // number of time steps to update the random forces
|
||||
class RanMars *random; // random number generator
|
||||
double *gfactor; // factors of random forces
|
||||
double *omega_H,*time_H; // H gives the desired power spectrum
|
||||
double **random_array_0, **random_array_1, **random_array_2; // random number arrays give independence between atoms and directions
|
||||
double **fran; // random forces
|
||||
double old_eavg; // average previous energies
|
||||
|
||||
// functions
|
||||
void couple();
|
||||
void remap(int);
|
||||
void check_alloc(int n);
|
||||
double compute_etotal();
|
||||
double compute_egrand();
|
||||
double compute_vol();
|
||||
double compute_vsum();
|
||||
double compute_hugoniot();
|
||||
double compute_rayleigh();
|
||||
double compute_lagrangian_speed();
|
||||
double compute_lagrangian_position();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
430
src/USER-QTB/fix_qtb.cpp
Normal file
430
src/USER-QTB/fix_qtb.cpp
Normal file
@ -0,0 +1,430 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Shen,Yuan, Qi,Tingting, and Reed,Evan
|
||||
Implementation of the colored thermostat for quantum nuclear effects
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "fix_qtb.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;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read parameters
|
||||
------------------------------------------------------------------------- */
|
||||
FixQTB::FixQTB(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg)
|
||||
{
|
||||
if (narg < 3) error->all(FLERR,"Illegal fix qtb command");
|
||||
|
||||
// default parameters
|
||||
global_freq = 1;
|
||||
extscalar = 1;
|
||||
nevery = 1;
|
||||
|
||||
t_target = 300.0;
|
||||
t_period = 1.0;
|
||||
fric_coef = 1/t_period;
|
||||
seed = 880302;
|
||||
f_max = 200.0;
|
||||
N_f = 100;
|
||||
|
||||
// reading parameters
|
||||
int iarg = 3;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"temp") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix qtb command");
|
||||
t_target = atof(arg[iarg+1]); if (t_target < 0.0) error->all(FLERR,"Fix qtb temp must be >= 0.0");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"damp") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix qtb command");
|
||||
t_period = atof(arg[iarg+1]); if (t_period <= 0.0) error->all(FLERR,"Fix qtb damp must be > 0.0"); fric_coef = 1/t_period;
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"seed") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix qtb command");
|
||||
seed = atof(arg[iarg+1]); if (seed <= 0) error->all(FLERR,"Illegal fix qtb command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"f_max") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix qtb command");
|
||||
f_max = atof(arg[iarg+1]); if (f_max <= 0) error->all(FLERR,"Illegal fix qtb command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"N_f") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix qtb command");
|
||||
N_f = atof(arg[iarg+1]); if (N_f <= 0) error->all(FLERR,"Illegal fix qtb command");
|
||||
iarg += 2;
|
||||
} else error->all(FLERR,"Illegal fix qtb command");
|
||||
}
|
||||
|
||||
// allocate qtb
|
||||
gfactor1 = NULL;
|
||||
gfactor3 = NULL;
|
||||
omega_H = NULL;
|
||||
time_H = NULL;
|
||||
random_array_0 = NULL;
|
||||
random_array_1 = NULL;
|
||||
random_array_2 = NULL;
|
||||
fran = NULL;
|
||||
id_temp = NULL;
|
||||
temperature = NULL;
|
||||
|
||||
// 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];
|
||||
gfactor3 = new double[atom->ntypes+1];
|
||||
|
||||
// allocate random-arrays and fran
|
||||
grow_arrays(atom->nmax);
|
||||
atom->add_callback(0);
|
||||
// memory->create(random_array_0,atom->nmax+300,2*N_f,"qtb:random_array_0");
|
||||
// memory->create(random_array_1,atom->nmax+300,2*N_f,"qtb:random_array_1");
|
||||
// memory->create(random_array_2,atom->nmax+300,2*N_f,"qtb:random_array_2");
|
||||
// memory->create(fran,atom->nmax+300,3,"qtb:fran");
|
||||
|
||||
// allocate omega_H and time_H
|
||||
memory->create(omega_H,2*N_f,"qtb:omega_H");
|
||||
memory->create(time_H,2*N_f,"qtb:time_H");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
release memories
|
||||
------------------------------------------------------------------------- */
|
||||
FixQTB::~FixQTB()
|
||||
{
|
||||
delete random;
|
||||
delete [] gfactor1;
|
||||
delete [] gfactor3;
|
||||
delete [] id_temp;
|
||||
memory->destroy(fran);
|
||||
memory->destroy(random_array_0);
|
||||
memory->destroy(random_array_1);
|
||||
memory->destroy(random_array_2);
|
||||
memory->destroy(omega_H);
|
||||
memory->destroy(time_H);
|
||||
atom->delete_callback(id,0);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
setmask
|
||||
------------------------------------------------------------------------- */
|
||||
int FixQTB::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= POST_FORCE;
|
||||
mask |= POST_FORCE_RESPA;
|
||||
mask |= THERMO_ENERGY;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
fix initiation
|
||||
------------------------------------------------------------------------- */
|
||||
void FixQTB::init()
|
||||
{
|
||||
// copy parameters from other classes
|
||||
double dtv = update->dt;
|
||||
if (atom->mass == NULL)
|
||||
error->all(FLERR,"Cannot use fix msst without per-type mass defined");
|
||||
|
||||
//initiate the counter \mu
|
||||
counter_mu=0;
|
||||
|
||||
//set up the h time step for updating the random force \delta{}h=\frac{\pi}{\Omega_{max}}
|
||||
if (int(1.0/(2*f_max*dtv)) == 0) {
|
||||
if (comm->me == 0) printf ("Warning: Either f_max is too high or the time step is too big, setting f_max to be 1/timestep!\n");
|
||||
h_timestep=dtv;
|
||||
alpha=1;
|
||||
} else {
|
||||
alpha=int(1.0/(2*f_max*dtv));
|
||||
h_timestep=alpha*dtv;
|
||||
}
|
||||
if (comm->me == 0) printf ("The effective maximum frequncy is now %f inverse time unit with alpha value as %d!\n", 0.5/h_timestep, alpha);
|
||||
|
||||
// set force prefactors
|
||||
if (!atom->rmass) {
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
//gfactor1 is the friction force \gamma{}m_{i}\frac{dv}{dt}
|
||||
gfactor1[i] = (atom->mass[i]*fric_coef) / force->ftm2v;
|
||||
//gfactor3 is the random force \sqrt{\frac{2\gamma{}m_{i}}{\alpha*\delta{}t}}, \sqrt{12} makes the random array variance equal to unit.
|
||||
gfactor3[i] = sqrt(2*fric_coef*atom->mass[i])*sqrt(force->mvv2e)*sqrt(12/h_timestep); //this still leaves a square energy term from the power spectrum H.
|
||||
}
|
||||
}
|
||||
|
||||
// generate random number array with zero mean and variance equal 1/12.
|
||||
int nlocal = atom->nlocal;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
for (int m = 0; m < 2*N_f; m++) {
|
||||
random_array_0[i][m] = random->uniform()-0.5;
|
||||
random_array_1[i][m] = random->uniform()-0.5;
|
||||
random_array_2[i][m] = random->uniform()-0.5;
|
||||
}
|
||||
}
|
||||
|
||||
// load omega_H with calculated spectrum at a specific temperature (corrected spectrum), omega_H is the Fourier transformation of time_H
|
||||
for (int k = 0; k < 2*N_f; k++) {
|
||||
double f_k=(k-N_f)/(2*N_f*h_timestep); //\omega_k=\frac{2\pi}{\delta{}h}\frac{k}{2N_f} for k from -N_f to N_f-1
|
||||
if(k == N_f) {
|
||||
omega_H[k]=sqrt(force->boltz * t_target);
|
||||
} else {
|
||||
double energy_k= force->hplanck * fabs(f_k);
|
||||
omega_H[k]=sqrt( energy_k * (0.5+1.0/( exp(energy_k/(force->boltz * t_target)) - 1.0 )) );
|
||||
omega_H[k]*=alpha*sin((k-N_f)*M_PI/(2*alpha*N_f))/sin((k-N_f)*M_PI/(2*N_f));
|
||||
}
|
||||
}
|
||||
|
||||
// construct the signal filter H, filter has the unit of of sqrt(energy) \sqrt{2N_f}^{-1}H\left(t_n\right)
|
||||
for (int n = 0; n < 2*N_f; n++) {
|
||||
time_H[n] = 0;
|
||||
double t_n=(n-N_f);
|
||||
for (int k = 0; k < 2*N_f; k++) {
|
||||
double omega_k=(k-N_f)*M_PI/N_f;
|
||||
time_H[n] += omega_H[k]*(cos(omega_k*t_n));
|
||||
}
|
||||
time_H[n]/=(2.0*N_f);
|
||||
}
|
||||
|
||||
// respa
|
||||
if (strstr(update->integrate_style,"respa"))
|
||||
nlevels_respa = ((Respa *) update->integrate)->nlevels;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
no MD, so setup returns post force
|
||||
------------------------------------------------------------------------- */
|
||||
void FixQTB::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);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
post_force
|
||||
------------------------------------------------------------------------- */
|
||||
void FixQTB::post_force(int vflag)
|
||||
{
|
||||
double gamma1,gamma3;
|
||||
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
bigint nlocal = atom->nlocal;
|
||||
bigint ntotal = atom->natoms;
|
||||
|
||||
//update the colored random force every alpha MD steps
|
||||
if (counter_mu == alpha) {
|
||||
//propagate h_timestep ahead
|
||||
for (int j = 0; j < nlocal; j++) {
|
||||
|
||||
//update random array
|
||||
for (int m = 0; m < 2*N_f-1; m++) {
|
||||
random_array_0[j][m] = random_array_0[j][m+1];
|
||||
random_array_1[j][m] = random_array_1[j][m+1];
|
||||
random_array_2[j][m] = random_array_2[j][m+1];
|
||||
}
|
||||
random_array_0[j][2*N_f-1] = random->uniform()-0.5;
|
||||
random_array_1[j][2*N_f-1] = random->uniform()-0.5;
|
||||
random_array_2[j][2*N_f-1] = random->uniform()-0.5;
|
||||
}
|
||||
|
||||
//reset counter \mu
|
||||
counter_mu=0;
|
||||
}
|
||||
|
||||
if (counter_mu == 0) {
|
||||
for (int j = 0; j < nlocal; j++) {
|
||||
fran[j][0] = 0.0;
|
||||
fran[j][1] = 0.0;
|
||||
fran[j][2] = 0.0;
|
||||
|
||||
//reset random force
|
||||
if (mask[j] & groupbit) {
|
||||
gamma3 = gfactor3[type[j]];
|
||||
|
||||
for (int m = 0; m < 2*N_f; m++) {
|
||||
fran[j][0] += time_H[m] * random_array_0[j][2*N_f-m-1];
|
||||
fran[j][1] += time_H[m] * random_array_1[j][2*N_f-m-1];
|
||||
fran[j][2] += time_H[m] * random_array_2[j][2*N_f-m-1];
|
||||
}
|
||||
fran[j][0] = fran[j][0]*gamma3;
|
||||
fran[j][1] = fran[j][1]*gamma3;
|
||||
fran[j][2] = fran[j][2]*gamma3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//reset all the force sums
|
||||
fsum[0]=0.0; fsumall[0]=0.0;
|
||||
fsum[1]=0.0; fsumall[1]=0.0;
|
||||
fsum[2]=0.0; fsumall[2]=0.0;
|
||||
|
||||
for (int j = 0; j < nlocal; j++) {
|
||||
//sum over each atom
|
||||
if (mask[j] & groupbit) {
|
||||
gamma1 = gfactor1[type[j]];
|
||||
|
||||
fsum[0]+=fran[j][0]-gamma1*v[j][0];
|
||||
fsum[1]+=fran[j][1]-gamma1*v[j][1];
|
||||
fsum[2]+=fran[j][2]-gamma1*v[j][2];
|
||||
}
|
||||
}
|
||||
|
||||
//compute force sums
|
||||
MPI_Allreduce(fsum,fsumall,3,MPI_DOUBLE,MPI_SUM,world);
|
||||
|
||||
//implement random forces
|
||||
for (int j = 0; j < nlocal; j++) {
|
||||
//make sure there is no net force on the system
|
||||
f[j][0] -= fsumall[0]/ntotal;
|
||||
f[j][1] -= fsumall[1]/ntotal;
|
||||
f[j][2] -= fsumall[2]/ntotal;
|
||||
|
||||
if (mask[j] & groupbit) {
|
||||
gamma1 = gfactor1[type[j]];
|
||||
|
||||
f[j][0]+=fran[j][0]-gamma1*v[j][0];
|
||||
f[j][1]+=fran[j][1]-gamma1*v[j][1];
|
||||
f[j][2]+=fran[j][2]-gamma1*v[j][2];
|
||||
}
|
||||
}
|
||||
|
||||
//move 1 step forward
|
||||
counter_mu++;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
post_force_respa
|
||||
------------------------------------------------------------------------- */
|
||||
void FixQTB::post_force_respa(int vflag, int ilevel, int iloop)
|
||||
{
|
||||
if (ilevel == nlevels_respa-1) post_force(vflag);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
modifications of fix qtb
|
||||
------------------------------------------------------------------------- */
|
||||
int FixQTB::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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of fix qtb
|
||||
------------------------------------------------------------------------- */
|
||||
double FixQTB::memory_usage()
|
||||
{
|
||||
double bytes = 0.0;
|
||||
// random_arrays memory usage
|
||||
bytes += (atom->nmax* 6*N_f * sizeof(double));
|
||||
// fran memory usage
|
||||
bytes += (atom->nmax* 3 * sizeof(double));
|
||||
bytes += (4*N_f * sizeof(double));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate atom-based array for fran and random_array
|
||||
------------------------------------------------------------------------- */
|
||||
void FixQTB::grow_arrays(int nmax)
|
||||
{
|
||||
memory->grow(random_array_0,nmax,2*N_f,"qtb:random_array_0");
|
||||
memory->grow(random_array_1,nmax,2*N_f,"qtb:random_array_1");
|
||||
memory->grow(random_array_2,nmax,2*N_f,"qtb:random_array_2");
|
||||
memory->grow(fran,nmax,3,"qtb:fran");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
copy values within local atom-based array
|
||||
------------------------------------------------------------------------- */
|
||||
void FixQTB::copy_arrays(int i, int j, int delflag)
|
||||
{
|
||||
for (int m = 0; m < 2*N_f; m++) {
|
||||
random_array_0[j][m] = random_array_0[i][m];
|
||||
random_array_1[j][m] = random_array_1[i][m];
|
||||
random_array_2[j][m] = random_array_2[i][m];
|
||||
}
|
||||
|
||||
for (int m = 0; m < 3; m++)
|
||||
fran[j][m] = fran[i][m];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack values in local atom-based array for exchange with another proc
|
||||
------------------------------------------------------------------------- */
|
||||
int FixQTB::pack_exchange(int i, double *buf)
|
||||
{
|
||||
for (int m = 0; m < 2*N_f; m++) buf[m] = random_array_0[i][m];
|
||||
for (int m = 0; m < 2*N_f; m++) buf[m+2*N_f] = random_array_1[i][m];
|
||||
for (int m = 0; m < 2*N_f; m++) buf[m+4*N_f] = random_array_2[i][m];
|
||||
for (int m = 0; m < 3; m++) buf[m+6*N_f] = fran[i][m];
|
||||
return 6*N_f+3;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
unpack values in local atom-based array from exchange with another proc
|
||||
------------------------------------------------------------------------- */
|
||||
int FixQTB::unpack_exchange(int nlocal, double *buf)
|
||||
{
|
||||
for (int m = 0; m < 2*N_f; m++) random_array_0[nlocal][m] = buf[m];
|
||||
for (int m = 0; m < 2*N_f; m++) random_array_1[nlocal][m] = buf[m+2*N_f];
|
||||
for (int m = 0; m < 2*N_f; m++) random_array_2[nlocal][m] = buf[m+4*N_f];
|
||||
for (int m = 0; m < 3; m++) fran[nlocal][m] = buf[m+6*N_f];
|
||||
return 6*N_f+3;
|
||||
}
|
||||
71
src/USER-QTB/fix_qtb.h
Normal file
71
src/USER-QTB/fix_qtb.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Shen,Yuan, Qi,Tingting, and Reed,Evan
|
||||
Implementation of the colored thermostat for quantum nuclear effects
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
|
||||
FixStyle(qtb,FixQTB)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_QTB_H
|
||||
#define LMP_FIX_QTB_H
|
||||
|
||||
#include "fix.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixQTB : public Fix {
|
||||
public:
|
||||
FixQTB(class LAMMPS *, int, char **);
|
||||
virtual ~FixQTB();
|
||||
int setmask();
|
||||
void init();
|
||||
void setup(int);
|
||||
void post_force(int);
|
||||
void post_force_respa(int, int, int);
|
||||
int modify_param(int, char **);
|
||||
double memory_usage();
|
||||
void grow_arrays(int);
|
||||
void copy_arrays(int, int, int);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(int, double *);
|
||||
|
||||
private:
|
||||
// qtb parameters
|
||||
int counter_mu; // counter l and mu
|
||||
double t_period, fric_coef; // friction coefficient
|
||||
int seed; // seed for the random number generator
|
||||
double f_max; // frequency cutoff
|
||||
int N_f; // number of frequency grid
|
||||
double t_target; // target qtb temperature
|
||||
char *id_temp;
|
||||
class Compute *temperature;
|
||||
double h_timestep; // time step to update the random forces
|
||||
int alpha; // number of time steps to update the random forces
|
||||
class RanMars *random; // random number generator
|
||||
double *gfactor1,*gfactor3; // factors of frictions and random forces
|
||||
double *omega_H,*time_H; // H gives the desired power spectrum
|
||||
double **random_array_0, **random_array_1, **random_array_2; // random number arrays give independence between atoms and directions
|
||||
int nlevels_respa;
|
||||
double **fran, fsum[3], fsumall[3]; // random forces and their sums
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user