diff --git a/src/fix_temp_csvr.cpp b/src/fix_temp_csvr.cpp index 81f87d4ca..3ef99ccd8 100644 --- a/src/fix_temp_csvr.cpp +++ b/src/fix_temp_csvr.cpp @@ -1,343 +1,344 @@ /* ---------------------------------------------------------------------- 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 author: Axel Kohlmeyer (Temple U) Based on code by Paolo Raiteri (Curtin U) and Giovanni Bussi (SISSA) ------------------------------------------------------------------------- */ #include <string.h> #include <stdlib.h> #include <math.h> #include "fix_temp_csvr.h" #include "atom.h" #include "force.h" #include "memory.h" #include "comm.h" #include "input.h" #include "variable.h" #include "group.h" #include "update.h" #include "modify.h" #include "compute.h" #include "random_mars.h" #include "error.h" using namespace LAMMPS_NS; using namespace FixConst; enum{NOBIAS,BIAS}; enum{CONSTANT,EQUAL}; double FixTempCSVR::gamdev(const int ia) { int j; double am,e,s,v1,v2,x,y; if (ia < 1) return 0.0; if (ia < 6) { x=1.0; for (j=1; j<=ia; j++) x *= random->uniform(); x = -log(x); } else { restart: do { do { do { v1 = random->uniform(); v2 = 2.0*random->uniform() - 1.0; } while (v1*v1 + v2*v2 > 1.0); y=v2/v1; am=ia-1; s=sqrt(2.0*am+1.0); x=s*y+am; } while (x <= 0.0); if (am*log(x/am)-s*y < -700 || v1<0.00001) { goto restart; } e=(1.0+y*y)*exp(am*log(x/am)-s*y); } while (random->uniform() > e); } return x; } /* ------------------------------------------------------------------- returns the sum of n independent gaussian noises squared (i.e. equivalent to summing the square of the return values of nn calls to gasdev) ---------------------------------------------------------------------- */ double FixTempCSVR::sumnoises(int nn) { if (nn == 0) { return 0.0; } else if (nn == 1) { const double rr = random->gaussian(); return rr*rr; } else if (nn % 2 == 0) { return 2.0 * gamdev(nn / 2); } else { const double rr = random->gaussian(); return 2.0 * gamdev((nn-1) / 2) + rr*rr; } } /* ------------------------------------------------------------------- returns the scaling factor for velocities to thermalize the system so it samples the canonical ensemble ---------------------------------------------------------------------- */ double FixTempCSVR::resamplekin(double ekin_old, double ekin_new){ const double tdof = temperature->dof; const double c1 = exp(-update->dt/t_period); const double c2 = (1.0-c1)*ekin_new/ekin_old/tdof; const double r1 = random->gaussian(); const double r2 = sumnoises(tdof - 1); const double scale = c1 + c2*(r1*r1+r2) + 2.0*r1*sqrt(c1*c2); return sqrt(scale); } /* ---------------------------------------------------------------------- */ FixTempCSVR::FixTempCSVR(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg) + Fix(lmp, narg, arg), + tstr(NULL), id_temp(NULL), random(NULL) { if (narg != 7) error->all(FLERR,"Illegal fix temp/csvr command"); // CSVR thermostat should be applied every step nevery = 1; scalar_flag = 1; global_freq = nevery; dynamic_group_allow = 1; extscalar = 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]); tstyle = EQUAL; } 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]); int seed = force->inumeric(FLERR,arg[6]); // error checks if (t_period <= 0.0) error->all(FLERR,"Illegal fix temp/csvr command"); if (seed <= 0) error->all(FLERR,"Illegal fix temp/csvr command"); random = new RanMars(lmp,seed + comm->me); // create a new compute temp style // id = fix-ID + temp, compute group = fix group int n = strlen(id) + 6; id_temp = new char[n]; strcpy(id_temp,id); strcat(id_temp,"_temp"); char **newarg = new char*[3]; newarg[0] = id_temp; newarg[1] = group->names[igroup]; newarg[2] = (char *) "temp"; modify->add_compute(3,newarg); delete [] newarg; tflag = 1; nmax = -1; energy = 0.0; } /* ---------------------------------------------------------------------- */ FixTempCSVR::~FixTempCSVR() { delete [] tstr; // delete temperature if fix created it if (tflag) modify->delete_compute(id_temp); delete [] id_temp; delete random; nmax = -1; } /* ---------------------------------------------------------------------- */ int FixTempCSVR::setmask() { int mask = 0; mask |= END_OF_STEP; mask |= THERMO_ENERGY; return mask; } /* ---------------------------------------------------------------------- */ void FixTempCSVR::init() { // check variable if (tstr) { tvar = input->variable->find(tstr); if (tvar < 0) error->all(FLERR,"Variable name for fix temp/csvr does not exist"); if (input->variable->equalstyle(tvar)) tstyle = EQUAL; else error->all(FLERR,"Variable for fix temp/csvr is invalid style"); } int icompute = modify->find_compute(id_temp); if (icompute < 0) error->all(FLERR,"Temperature ID for fix temp/csvr does not exist"); temperature = modify->compute[icompute]; if (temperature->tempbias) which = BIAS; else which = NOBIAS; } /* ---------------------------------------------------------------------- */ void FixTempCSVR::end_of_step() { // set current t_target // if variable temp, evaluate variable, wrap with clear/add double delta = update->ntimestep - update->beginstep; if (delta != 0.0) delta /= update->endstep - update->beginstep; if (tstyle == CONSTANT) t_target = t_start + delta * (t_stop-t_start); else { modify->clearstep_compute(); t_target = input->variable->compute_equal(tvar); if (t_target < 0.0) error->one(FLERR, "Fix temp/csvr variable returned negative temperature"); modify->addstep_compute(update->ntimestep + nevery); } const double t_current = temperature->compute_scalar(); const double efactor = 0.5 * temperature->dof * force->boltz; const double ekin_old = t_current * efactor; const double ekin_new = t_target * efactor; // there is nothing to do, if there are no degrees of freedom if (temperature->dof < 1) return; // compute velocity scaling factor on root node and broadcast double lamda; if (comm->me == 0) { lamda = resamplekin(ekin_old, ekin_new); } MPI_Bcast(&lamda,1,MPI_DOUBLE,0,world); double * const * const v = atom->v; const int * const mask = atom->mask; const int nlocal = atom->nlocal; if (which == NOBIAS) { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { v[i][0] *= lamda; v[i][1] *= lamda; v[i][2] *= lamda; } } } else { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { temperature->remove_bias(i,v[i]); v[i][0] *= lamda; v[i][1] *= lamda; v[i][2] *= lamda; temperature->restore_bias(i,v[i]); } } } // tally the kinetic energy transferred between heat bath and system energy += ekin_old * (1.0 - lamda*lamda); } /* ---------------------------------------------------------------------- */ int FixTempCSVR::modify_param(int narg, char **arg) { if (strcmp(arg[0],"temp") == 0) { if (narg < 2) error->all(FLERR,"Illegal fix_modify command"); if (tflag) { modify->delete_compute(id_temp); tflag = 0; } 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; } /* ---------------------------------------------------------------------- */ void FixTempCSVR::reset_target(double t_new) { t_target = t_start = t_stop = t_new; } /* ---------------------------------------------------------------------- */ double FixTempCSVR::compute_scalar() { return energy; } /* ---------------------------------------------------------------------- extract thermostat properties ------------------------------------------------------------------------- */ void *FixTempCSVR::extract(const char *str, int &dim) { dim=0; if (strcmp(str,"t_target") == 0) { return &t_target; } return NULL; } diff --git a/src/fix_temp_rescale.cpp b/src/fix_temp_rescale.cpp index 5e6036214..8af39df51 100644 --- a/src/fix_temp_rescale.cpp +++ b/src/fix_temp_rescale.cpp @@ -1,256 +1,257 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include <string.h> #include <stdlib.h> #include <math.h> #include "fix_temp_rescale.h" #include "atom.h" #include "force.h" #include "group.h" #include "update.h" #include "domain.h" #include "region.h" #include "comm.h" #include "input.h" #include "variable.h" #include "modify.h" #include "compute.h" #include "error.h" using namespace LAMMPS_NS; using namespace FixConst; enum{NOBIAS,BIAS}; enum{CONSTANT,EQUAL}; /* ---------------------------------------------------------------------- */ FixTempRescale::FixTempRescale(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg) + Fix(lmp, narg, arg), + tstr(NULL), id_temp(NULL), tflag(0) { if (narg < 8) error->all(FLERR,"Illegal fix temp/rescale command"); nevery = force->inumeric(FLERR,arg[3]); if (nevery <= 0) error->all(FLERR,"Illegal fix temp/rescale command"); scalar_flag = 1; global_freq = nevery; extscalar = 1; tstr = NULL; if (strstr(arg[4],"v_") == arg[4]) { int n = strlen(&arg[4][2]) + 1; tstr = new char[n]; strcpy(tstr,&arg[4][2]); tstyle = EQUAL; } else { t_start = force->numeric(FLERR,arg[4]); t_target = t_start; tstyle = CONSTANT; } t_stop = force->numeric(FLERR,arg[5]); t_window = force->numeric(FLERR,arg[6]); fraction = force->numeric(FLERR,arg[7]); // create a new compute temp // id = fix-ID + temp, compute group = fix group int n = strlen(id) + 6; id_temp = new char[n]; strcpy(id_temp,id); strcat(id_temp,"_temp"); char **newarg = new char*[6]; newarg[0] = id_temp; newarg[1] = group->names[igroup]; newarg[2] = (char *) "temp"; modify->add_compute(3,newarg); delete [] newarg; tflag = 1; energy = 0.0; } /* ---------------------------------------------------------------------- */ FixTempRescale::~FixTempRescale() { delete [] tstr; // delete temperature if fix created it if (tflag) modify->delete_compute(id_temp); delete [] id_temp; } /* ---------------------------------------------------------------------- */ int FixTempRescale::setmask() { int mask = 0; mask |= END_OF_STEP; mask |= THERMO_ENERGY; return mask; } /* ---------------------------------------------------------------------- */ void FixTempRescale::init() { // check variable if (tstr) { tvar = input->variable->find(tstr); if (tvar < 0) error->all(FLERR,"Variable name for fix temp/rescale does not exist"); if (input->variable->equalstyle(tvar)) tstyle = EQUAL; else error->all(FLERR,"Variable for fix temp/rescale is invalid style"); } int icompute = modify->find_compute(id_temp); if (icompute < 0) error->all(FLERR,"Temperature ID for fix temp/rescale does not exist"); temperature = modify->compute[icompute]; if (temperature->tempbias) which = BIAS; else which = NOBIAS; } /* ---------------------------------------------------------------------- */ void FixTempRescale::end_of_step() { double t_current = temperature->compute_scalar(); // there is nothing to do, if there are no degrees of freedom if (temperature->dof < 1) return; // protect against division by zero. if (t_current == 0.0) error->all(FLERR,"Computed temperature for fix temp/rescale cannot be 0.0"); double delta = update->ntimestep - update->beginstep; if (delta != 0.0) delta /= update->endstep - update->beginstep; // set current t_target // if variable temp, evaluate variable, wrap with clear/add if (tstyle == CONSTANT) t_target = t_start + delta * (t_stop-t_start); else { modify->clearstep_compute(); t_target = input->variable->compute_equal(tvar); if (t_target < 0.0) error->one(FLERR, "Fix temp/rescale variable returned negative temperature"); modify->addstep_compute(update->ntimestep + nevery); } // rescale velocity of appropriate atoms if outside window // for BIAS: // temperature is current, so do not need to re-compute // OK to not test returned v = 0, since factor is multiplied by v if (fabs(t_current-t_target) > t_window) { t_target = t_current - fraction*(t_current-t_target); double factor = sqrt(t_target/t_current); double efactor = 0.5 * force->boltz * temperature->dof; double **v = atom->v; int *mask = atom->mask; int nlocal = atom->nlocal; energy += (t_current-t_target) * efactor; if (which == NOBIAS) { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { v[i][0] *= factor; v[i][1] *= factor; v[i][2] *= factor; } } } else { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { temperature->remove_bias(i,v[i]); v[i][0] *= factor; v[i][1] *= factor; v[i][2] *= factor; temperature->restore_bias(i,v[i]); } } } } } /* ---------------------------------------------------------------------- */ int FixTempRescale::modify_param(int narg, char **arg) { if (strcmp(arg[0],"temp") == 0) { if (narg < 2) error->all(FLERR,"Illegal fix_modify command"); if (tflag) { modify->delete_compute(id_temp); tflag = 0; } 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; } /* ---------------------------------------------------------------------- */ void FixTempRescale::reset_target(double t_new) { t_target = t_start = t_stop = t_new; } /* ---------------------------------------------------------------------- */ double FixTempRescale::compute_scalar() { return energy; } /* ---------------------------------------------------------------------- extract thermostat properties ------------------------------------------------------------------------- */ void *FixTempRescale::extract(const char *str, int &dim) { if (strcmp(str,"t_target") == 0) { dim = 0; return &t_target; } return NULL; } diff --git a/src/fix_tmd.cpp b/src/fix_tmd.cpp index d32668536..a94fbdcad 100644 --- a/src/fix_tmd.cpp +++ b/src/fix_tmd.cpp @@ -1,547 +1,546 @@ /* ---------------------------------------------------------------------- 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: Paul Crozier (SNL) Christian Burisch (Bochum Univeristy, Germany) ------------------------------------------------------------------------- */ #include <mpi.h> #include <math.h> #include <stdlib.h> #include <string.h> #include "fix_tmd.h" #include "atom.h" #include "update.h" #include "modify.h" #include "domain.h" #include "group.h" #include "respa.h" #include "force.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace FixConst; #define CHUNK 1000 #define MAXLINE 256 /* ---------------------------------------------------------------------- */ -FixTMD::FixTMD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) +FixTMD::FixTMD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), +nfileevery(0), fp(NULL), xf(NULL), xold(NULL) { if (narg < 6) error->all(FLERR,"Illegal fix tmd command"); rho_stop = force->numeric(FLERR,arg[3]); nfileevery = force->inumeric(FLERR,arg[5]); if (rho_stop < 0 || nfileevery < 0) error->all(FLERR,"Illegal fix tmd command"); if (nfileevery && narg != 7) error->all(FLERR,"Illegal fix tmd command"); MPI_Comm_rank(world,&me); // perform initial allocation of atom-based arrays // register with Atom class - xf = NULL; - xold = NULL; grow_arrays(atom->nmax); atom->add_callback(0); // make sure an atom map exists before reading in target coordinates if (atom->map_style == 0) error->all(FLERR,"Cannot use fix TMD unless atom map exists"); // read from arg[4] and store coordinates of final target in xf readfile(arg[4]); // open arg[6] statistics file and write header if (nfileevery) { if (narg != 7) error->all(FLERR,"Illegal fix tmd command"); if (me == 0) { fp = fopen(arg[6],"w"); if (fp == NULL) { char str[128]; sprintf(str,"Cannot open fix tmd file %s",arg[6]); error->one(FLERR,str); } fprintf(fp,"%s %s\n","# Step rho_target rho_old gamma_back", "gamma_forward lambda work_lambda work_analytical"); } } masstotal = group->mass(igroup); if (masstotal == 0.0) error->all(FLERR,"Cannot use fix TMD on massless group"); // rho_start = initial rho // xold = initial x or 0.0 if not in group int *mask = atom->mask; int *type = atom->type; imageint *image = atom->image; double **x = atom->x; double *mass = atom->mass; int nlocal = atom->nlocal; double dx,dy,dz; rho_start = 0.0; for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { domain->unmap(x[i],image[i],xold[i]); dx = xold[i][0] - xf[i][0]; dy = xold[i][1] - xf[i][1]; dz = xold[i][2] - xf[i][2]; rho_start += mass[type[i]]*(dx*dx + dy*dy + dz*dz); } else xold[i][0] = xold[i][1] = xold[i][2] = 0.0; } double rho_start_total; MPI_Allreduce(&rho_start,&rho_start_total,1,MPI_DOUBLE,MPI_SUM,world); rho_start = sqrt(rho_start_total/masstotal); rho_old = rho_start; work_lambda = 0.0; work_analytical = 0.0; previous_stat = 0; } /* ---------------------------------------------------------------------- */ FixTMD::~FixTMD() { if (nfileevery && me == 0) fclose(fp); // unregister callbacks to this fix from Atom class atom->delete_callback(id,0); // delete locally stored arrays memory->destroy(xf); memory->destroy(xold); } /* ---------------------------------------------------------------------- */ int FixTMD::setmask() { int mask = 0; mask |= INITIAL_INTEGRATE; mask |= INITIAL_INTEGRATE_RESPA; return mask; } /* ---------------------------------------------------------------------- */ void FixTMD::init() { // check that no integrator fix comes after a TMD fix int flag = 0; for (int i = 0; i < modify->nfix; i++) { if (strcmp(modify->fix[i]->style,"tmd") == 0) flag = 1; if (flag && modify->fix[i]->time_integrate) flag = 2; } if (flag == 2) error->all(FLERR,"Fix tmd must come after integration fixes"); // timesteps dtv = update->dt; dtf = update->dt * force->ftm2v; if (strstr(update->integrate_style,"respa")) step_respa = ((Respa *) update->integrate)->step; } /* ---------------------------------------------------------------------- */ void FixTMD::initial_integrate(int vflag) { double a,b,c,d,e; double dx,dy,dz,dxkt,dykt,dzkt; double dxold,dyold,dzold,xback,yback,zback; double gamma_forward,gamma_back,gamma_max,lambda; double kt,fr,kttotal,frtotal,dtfm; double unwrap[3]; double **x = atom->x; double **v = atom->v; double **f = atom->f; double *mass = atom->mass; imageint *image = atom->image; int *type = atom->type; int *mask = atom->mask; int nlocal = atom->nlocal; double delta = update->ntimestep - update->beginstep; if (delta != 0.0) delta /= update->endstep - update->beginstep; double rho_target = rho_start + delta * (rho_stop - rho_start); // compute the Lagrange multiplier a = b = e = 0.0; for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dxold = xold[i][0] - xf[i][0]; dyold = xold[i][1] - xf[i][1]; dzold = xold[i][2] - xf[i][2]; domain->unmap(x[i],image[i],unwrap); dx = unwrap[0] - xf[i][0]; dy = unwrap[1] - xf[i][1]; dz = unwrap[2] - xf[i][2]; a += mass[type[i]]*(dxold*dxold + dyold*dyold + dzold*dzold); b += mass[type[i]]*(dx *dxold + dy *dyold + dz *dzold); e += mass[type[i]]*(dx *dx + dy *dy + dz *dz); } } double abe[3],abetotal[3]; abe[0] = a; abe[1] = b; abe[2] = e; MPI_Allreduce(abe,abetotal,3,MPI_DOUBLE,MPI_SUM,world); a = abetotal[0]/masstotal; b = 2.0*abetotal[1]/masstotal; e = abetotal[2]/masstotal; c = e - rho_old*rho_old; d = b*b - 4*a*c; if (d < 0) d = 0; if (b >= 0) gamma_max = (-b - sqrt(d))/(2*a); else gamma_max = (-b + sqrt(d))/(2*a); gamma_back = c/(a*gamma_max); if (a == 0.0) gamma_back = 0; c = e - rho_target*rho_target; d = b*b - 4*a*c; if (d < 0) d = 0; if (b >= 0) gamma_max = (-b - sqrt(d))/(2*a); else gamma_max = (-b + sqrt(d))/(2*a); gamma_forward = c/(a*gamma_max); if (a == 0.0) gamma_forward = 0; fr = kt = 0.0; for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dxold = xold[i][0] - xf[i][0]; dyold = xold[i][1] - xf[i][1]; dzold = xold[i][2] - xf[i][2]; domain->unmap(x[i],image[i],unwrap); xback = unwrap[0] + gamma_back*dxold; yback = unwrap[1] + gamma_back*dyold; zback = unwrap[2] + gamma_back*dzold; dxkt = xback - xold[i][0]; dykt = yback - xold[i][1]; dzkt = zback - xold[i][2]; kt += mass[type[i]]*(dxkt*dxkt + dykt*dykt + dzkt*dzkt); fr += f[i][0]*dxold + f[i][1]*dyold + f[i][2]*dzold; } } double r[2],rtotal[2]; r[0] = fr; r[1] = kt; MPI_Allreduce(r,rtotal,2,MPI_DOUBLE,MPI_SUM,world); frtotal = rtotal[0]; kttotal = rtotal[1]; // stat write of mean constraint force based on previous time step constraint if (nfileevery && me == 0) { work_analytical += (-frtotal - kttotal/dtv/dtf)*(rho_target - rho_old)/rho_old; lambda = gamma_back*rho_old*masstotal/dtv/dtf; work_lambda += lambda*(rho_target - rho_old); if (!(update->ntimestep % nfileevery) && (previous_stat != update->ntimestep)) { fprintf(fp, BIGINT_FORMAT " %g %g %g %g %g %g %g\n", update->ntimestep,rho_target,rho_old, gamma_back,gamma_forward,lambda,work_lambda,work_analytical); fflush(fp); previous_stat = update->ntimestep; } } rho_old = rho_target; // apply the constraint and save constrained positions for next step for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dtfm = dtf / mass[type[i]]; dxold = xold[i][0] - xf[i][0]; x[i][0] += gamma_forward*dxold; v[i][0] += gamma_forward*dxold/dtv; f[i][0] += gamma_forward*dxold/dtv/dtfm; dyold = xold[i][1] - xf[i][1]; x[i][1] += gamma_forward*dyold; v[i][1] += gamma_forward*dyold/dtv; f[i][1] += gamma_forward*dyold/dtv/dtfm; dzold = xold[i][2] - xf[i][2]; x[i][2] += gamma_forward*dzold; v[i][2] += gamma_forward*dzold/dtv; f[i][2] += gamma_forward*dzold/dtv/dtfm; domain->unmap(x[i],image[i],xold[i]); } } } /* ---------------------------------------------------------------------- */ void FixTMD::initial_integrate_respa(int vflag, int ilevel, int flag) { if (flag) return; // only used by NPT,NPH dtv = step_respa[ilevel]; dtf = step_respa[ilevel] * force->ftm2v; if (ilevel == 0) initial_integrate(vflag); } /* ---------------------------------------------------------------------- memory usage of local atom-based arrays ------------------------------------------------------------------------- */ double FixTMD::memory_usage() { double bytes = 2*atom->nmax*3 * sizeof(double); return bytes; } /* ---------------------------------------------------------------------- allocate atom-based arrays ------------------------------------------------------------------------- */ void FixTMD::grow_arrays(int nmax) { memory->grow(xf,nmax,3,"fix_tmd:xf"); memory->grow(xold,nmax,3,"fix_tmd:xold"); } /* ---------------------------------------------------------------------- copy values within local atom-based arrays ------------------------------------------------------------------------- */ void FixTMD::copy_arrays(int i, int j, int delflag) { xf[j][0] = xf[i][0]; xf[j][1] = xf[i][1]; xf[j][2] = xf[i][2]; xold[j][0] = xold[i][0]; xold[j][1] = xold[i][1]; xold[j][2] = xold[i][2]; } /* ---------------------------------------------------------------------- pack values in local atom-based arrays for exchange with another proc ------------------------------------------------------------------------- */ int FixTMD::pack_exchange(int i, double *buf) { buf[0] = xf[i][0]; buf[1] = xf[i][1]; buf[2] = xf[i][2]; buf[3] = xold[i][0]; buf[4] = xold[i][1]; buf[5] = xold[i][2]; return 6; } /* ---------------------------------------------------------------------- unpack values in local atom-based arrays from exchange with another proc ------------------------------------------------------------------------- */ int FixTMD::unpack_exchange(int nlocal, double *buf) { xf[nlocal][0] = buf[0]; xf[nlocal][1] = buf[1]; xf[nlocal][2] = buf[2]; xold[nlocal][0] = buf[3]; xold[nlocal][1] = buf[4]; xold[nlocal][2] = buf[5]; return 6; } /* ---------------------------------------------------------------------- read target coordinates from file, store with appropriate atom ------------------------------------------------------------------------- */ void FixTMD::readfile(char *file) { if (me == 0) { if (screen) fprintf(screen,"Reading TMD target file %s ...\n",file); open(file); } int *mask = atom->mask; int nlocal = atom->nlocal; char *buffer = new char[CHUNK*MAXLINE]; char *next,*bufptr; int i,m,nlines,imageflag,ix,iy,iz; tagint itag; double x,y,z,xprd,yprd,zprd; int firstline = 1; int ncount = 0; char *eof = NULL; xprd = yprd = zprd = -1.0; while (!eof) { if (me == 0) { m = 0; for (nlines = 0; nlines < CHUNK; nlines++) { eof = fgets(&buffer[m],MAXLINE,fp); if (eof == NULL) break; m += strlen(&buffer[m]); } if (buffer[m-1] != '\n') strcpy(&buffer[m++],"\n"); m++; } MPI_Bcast(&eof,1,MPI_INT,0,world); MPI_Bcast(&nlines,1,MPI_INT,0,world); MPI_Bcast(&m,1,MPI_INT,0,world); MPI_Bcast(buffer,m,MPI_CHAR,0,world); bufptr = buffer; for (i = 0; i < nlines; i++) { next = strchr(bufptr,'\n'); *next = '\0'; if (firstline) { if (strstr(bufptr,"xlo xhi")) { double lo,hi; sscanf(bufptr,"%lg %lg",&lo,&hi); xprd = hi - lo; bufptr = next + 1; continue; } else if (strstr(bufptr,"ylo yhi")) { double lo,hi; sscanf(bufptr,"%lg %lg",&lo,&hi); yprd = hi - lo; bufptr = next + 1; continue; } else if (strstr(bufptr,"zlo zhi")) { double lo,hi; sscanf(bufptr,"%lg %lg",&lo,&hi); zprd = hi - lo; bufptr = next + 1; continue; } else if (atom->count_words(bufptr) == 4) { if (xprd >= 0.0 || yprd >= 0.0 || zprd >= 0.0) error->all(FLERR,"Incorrect format in TMD target file"); imageflag = 0; firstline = 0; } else if (atom->count_words(bufptr) == 7) { if (xprd < 0.0 || yprd < 0.0 || zprd < 0.0) error->all(FLERR,"Incorrect format in TMD target file"); imageflag = 1; firstline = 0; } else error->all(FLERR,"Incorrect format in TMD target file"); } if (imageflag) sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg %d %d %d", &itag,&x,&y,&z,&ix,&iy,&iz); else sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg",&itag,&x,&y,&z); m = atom->map(itag); if (m >= 0 && m < nlocal && mask[m] & groupbit) { if (imageflag) { xf[m][0] = x + ix*xprd; xf[m][1] = y + iy*yprd; xf[m][2] = z + iz*zprd; } else { xf[m][0] = x; xf[m][1] = y; xf[m][2] = z; } ncount++; } bufptr = next + 1; } } // clean up delete [] buffer; if (me == 0) { if (compressed) pclose(fp); else fclose(fp); } // check that all atoms in group were listed in target file // set xf = 0.0 for atoms not in group int gcount = 0; for (i = 0; i < nlocal; i++) if (mask[i] & groupbit) gcount++; else xf[i][0] = xf[i][1] = xf[i][2] = 0.0; int flag = 0; if (gcount != ncount) flag = 1; int flagall; MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); if (flagall) error->all(FLERR,"TMD target file did not list all group atoms"); } /* ---------------------------------------------------------------------- proc 0 opens TMD data file test if gzipped ------------------------------------------------------------------------- */ void FixTMD::open(char *file) { compressed = 0; char *suffix = file + strlen(file) - 3; if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1; if (!compressed) fp = fopen(file,"r"); else { #ifdef LAMMPS_GZIP char gunzip[128]; sprintf(gunzip,"gzip -c -d %s",file); #ifdef _WIN32 fp = _popen(gunzip,"rb"); #else fp = popen(gunzip,"r"); #endif #else error->one(FLERR,"Cannot open gzipped file"); #endif } if (fp == NULL) { char str[128]; sprintf(str,"Cannot open file %s",file); error->one(FLERR,str); } } /* ---------------------------------------------------------------------- */ void FixTMD::reset_dt() { dtv = update->dt; dtf = update->dt * force->ftm2v; } diff --git a/src/fix_vector.cpp b/src/fix_vector.cpp index d4bd3087d..07841d5ba 100644 --- a/src/fix_vector.cpp +++ b/src/fix_vector.cpp @@ -1,337 +1,339 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include <string.h> #include "fix_vector.h" #include "update.h" #include "force.h" #include "modify.h" #include "compute.h" #include "group.h" #include "input.h" #include "variable.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace FixConst; enum{COMPUTE,FIX,VARIABLE}; enum{ONE,RUNNING,WINDOW}; enum{SCALAR,VECTOR}; #define INVOKED_SCALAR 1 #define INVOKED_VECTOR 2 #define INVOKED_ARRAY 4 /* ---------------------------------------------------------------------- */ FixVector::FixVector(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg) + Fix(lmp, narg, arg), + nvalues(0), which(NULL), argindex(NULL), value2index(NULL), ids(NULL), vector(NULL), array(NULL) { if (narg < 5) error->all(FLERR,"Illegal fix vector command"); nevery = force->inumeric(FLERR,arg[3]); if (nevery <= 0) error->all(FLERR,"Illegal fix vector command"); nvalues = narg-4; which = new int[nvalues]; argindex = new int[nvalues]; value2index = new int[nvalues]; ids = new char*[nvalues]; nvalues = 0; for (int iarg = 4; iarg < narg; iarg++) { if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE; else if (arg[iarg][0] == 'f') which[nvalues] = FIX; else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE; else error->all(FLERR,"Illegal fix vector command"); int n = strlen(arg[iarg]); char *suffix = new char[n]; strcpy(suffix,&arg[iarg][2]); char *ptr = strchr(suffix,'['); if (ptr) { if (suffix[strlen(suffix)-1] != ']') error->all(FLERR,"Illegal fix vector command"); argindex[nvalues] = atoi(ptr+1); *ptr = '\0'; } else argindex[nvalues] = 0; n = strlen(suffix) + 1; ids[nvalues] = new char[n]; strcpy(ids[nvalues],suffix); delete [] suffix; nvalues++; } // setup and error check // for fix inputs, check that fix frequency is acceptable for (int i = 0; i < nvalues; i++) { if (which[i] == COMPUTE) { int icompute = modify->find_compute(ids[i]); if (icompute < 0) error->all(FLERR,"Compute ID for fix vector does not exist"); if (argindex[i] == 0 && modify->compute[icompute]->scalar_flag == 0) error->all(FLERR,"Fix vector compute does not calculate a scalar"); if (argindex[i] && modify->compute[icompute]->vector_flag == 0) error->all(FLERR,"Fix vector compute does not calculate a vector"); if (argindex[i] && argindex[i] > modify->compute[icompute]->size_vector) error->all(FLERR, "Fix vector compute vector is accessed out-of-range"); } else if (which[i] == FIX) { int ifix = modify->find_fix(ids[i]); if (ifix < 0) error->all(FLERR,"Fix ID for fix vector does not exist"); if (argindex[i] == 0 && modify->fix[ifix]->scalar_flag == 0) error->all(FLERR,"Fix vector fix does not calculate a scalar"); if (argindex[i] && modify->fix[ifix]->vector_flag == 0) error->all(FLERR,"Fix vector fix does not calculate a vector"); if (argindex[i] && argindex[i] > modify->fix[ifix]->size_vector) error->all(FLERR,"Fix vector fix vector is accessed out-of-range"); if (nevery % modify->fix[ifix]->global_freq) error->all(FLERR, "Fix for fix vector not computed at compatible time"); } else if (which[i] == VARIABLE) { int ivariable = input->variable->find(ids[i]); if (ivariable < 0) error->all(FLERR,"Variable name for fix vector does not exist"); if (argindex[i] == 0 && input->variable->equalstyle(ivariable) == 0) error->all(FLERR,"Fix vector variable is not equal-style variable"); if (argindex[i] && input->variable->vectorstyle(ivariable) == 0) error->all(FLERR,"Fix vector variable is not vector-style variable"); } } // this fix produces either a global vector or array // intensive/extensive flags set by compute,fix,variable that produces value int value,finalvalue; for (int i = 0; i < nvalues; i++) { if (which[i] == COMPUTE) { Compute *compute = modify->compute[modify->find_compute(ids[i])]; if (argindex[0] == 0) value = compute->extscalar; else if (compute->extvector >= 0) value = compute->extvector; else value = compute->extlist[argindex[0]-1]; } else if (which[i] == FIX) { Fix *fix = modify->fix[modify->find_fix(ids[i])]; if (argindex[i] == 0) value = fix->extvector; else value = fix->extarray; } else if (which[i] == VARIABLE) value = 0; if (i == 0) finalvalue = value; else if (value != finalvalue) error->all(FLERR,"Fix vector cannot set output array " "intensive/extensive from these inputs"); } if (nvalues == 1) { vector_flag = 1; extvector = finalvalue; } else { array_flag = 1; size_array_cols = nvalues; extarray = finalvalue; } global_freq = nevery; time_depend = 1; // ncount = current size of vector or array vector = NULL; array = NULL; ncount = ncountmax = 0; if (nvalues == 1) size_vector = 0; else size_array_rows = 0; // nextstep = next step on which end_of_step does something // add nextstep to all computes that store invocation times // since don't know a priori which are invoked by this fix // once in end_of_step() can set timestep for ones actually invoked nextstep = (update->ntimestep/nevery)*nevery; if (nextstep < update->ntimestep) nextstep += nevery; modify->addstep_compute_all(nextstep); // initialstep = first step the vector/array will store values for initialstep = nextstep; } /* ---------------------------------------------------------------------- */ FixVector::~FixVector() { delete [] which; delete [] argindex; delete [] value2index; for (int i = 0; i < nvalues; i++) delete [] ids[i]; delete [] ids; memory->destroy(vector); memory->destroy(array); } /* ---------------------------------------------------------------------- */ int FixVector::setmask() { int mask = 0; mask |= END_OF_STEP; return mask; } /* ---------------------------------------------------------------------- */ void FixVector::init() { // set current indices for all computes,fixes,variables for (int i = 0; i < nvalues; i++) { if (which[i] == COMPUTE) { int icompute = modify->find_compute(ids[i]); if (icompute < 0) error->all(FLERR,"Compute ID for fix vector does not exist"); value2index[i] = icompute; } else if (which[i] == FIX) { int ifix = modify->find_fix(ids[i]); if (ifix < 0) error->all(FLERR,"Fix ID for fix vector does not exist"); value2index[i] = ifix; } else if (which[i] == VARIABLE) { int ivariable = input->variable->find(ids[i]); if (ivariable < 0) error->all(FLERR,"Variable name for fix vector does not exist"); value2index[i] = ivariable; } } // reallocate vector or array for accumulated size at end of run // use endstep to allow for subsequent runs with "pre no" // nsize = # of entries from initialstep to finalstep bigint finalstep = update->endstep/nevery * nevery; if (finalstep > update->endstep) finalstep -= nevery; ncountmax = (finalstep-initialstep)/nevery + 1; if (nvalues == 1) memory->grow(vector,ncountmax,"vector:vector"); else memory->grow(array,ncountmax,nvalues,"vector:array"); } /* ---------------------------------------------------------------------- only does something if nvalid = current timestep ------------------------------------------------------------------------- */ void FixVector::setup(int vflag) { end_of_step(); } /* ---------------------------------------------------------------------- */ void FixVector::end_of_step() { // skip if not step which requires doing something if (update->ntimestep != nextstep) return; if (ncount == ncountmax) error->all(FLERR,"Overflow of allocated fix vector storage"); // accumulate results of computes,fixes,variables to local copy // compute/fix/variable may invoke computes so wrap with clear/add double *result; if (nvalues == 1) result = &vector[ncount]; else result = array[ncount]; modify->clearstep_compute(); for (int i = 0; i < nvalues; i++) { int m = value2index[i]; // invoke compute if not previously invoked if (which[i] == COMPUTE) { Compute *compute = modify->compute[m]; if (argindex[i] == 0) { if (!(compute->invoked_flag & INVOKED_SCALAR)) { compute->compute_scalar(); compute->invoked_flag |= INVOKED_SCALAR; } result[i] = compute->scalar; } else { if (!(compute->invoked_flag & INVOKED_VECTOR)) { compute->compute_vector(); compute->invoked_flag |= INVOKED_VECTOR; } result[i] = compute->vector[argindex[i]-1]; } // access fix fields, guaranteed to be ready } else if (which[i] == FIX) { if (argindex[i] == 0) result[i] = modify->fix[m]->compute_scalar(); else result[i] = modify->fix[m]->compute_vector(argindex[i]-1); // evaluate equal-style or vector-style variable - } else if (which[i] == VARIABLE) - if (argindex[i] == 0) + } else if (which[i] == VARIABLE) { + if (argindex[i] == 0) result[i] = input->variable->compute_equal(m); else { double *varvec; int nvec = input->variable->compute_vector(m,&varvec); int index = argindex[i]; if (nvec < index) result[i] = 0.0; else result[i] = varvec[index-1]; } + } } // trigger computes on next needed step nextstep += nevery; modify->addstep_compute(nextstep); // update size of vector or array ncount++; if (nvalues == 1) size_vector++; else size_array_rows++; } /* ---------------------------------------------------------------------- return Ith vector value ------------------------------------------------------------------------- */ double FixVector::compute_vector(int i) { return vector[i]; } /* ---------------------------------------------------------------------- return I,J array value ------------------------------------------------------------------------- */ double FixVector::compute_array(int i, int j) { return array[i][j]; } diff --git a/src/fix_viscous.cpp b/src/fix_viscous.cpp index 9c82b34d8..911fcf84e 100644 --- a/src/fix_viscous.cpp +++ b/src/fix_viscous.cpp @@ -1,144 +1,145 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include <math.h> #include <stdlib.h> #include <string.h> #include "fix_viscous.h" #include "atom.h" #include "update.h" #include "respa.h" #include "error.h" #include "force.h" using namespace LAMMPS_NS; using namespace FixConst; /* ---------------------------------------------------------------------- */ FixViscous::FixViscous(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg) + Fix(lmp, narg, arg), + gamma(NULL) { if (narg < 4) error->all(FLERR,"Illegal fix viscous command"); double gamma_one = force->numeric(FLERR,arg[3]); gamma = new double[atom->ntypes+1]; for (int i = 1; i <= atom->ntypes; i++) gamma[i] = gamma_one; // optional args int iarg = 4; while (iarg < narg) { if (strcmp(arg[iarg],"scale") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal fix viscous 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 viscous command"); gamma[itype] = gamma_one * scale; iarg += 3; } else error->all(FLERR,"Illegal fix viscous command"); } respa_level_support = 1; ilevel_respa = 0; } /* ---------------------------------------------------------------------- */ FixViscous::~FixViscous() { delete [] gamma; } /* ---------------------------------------------------------------------- */ int FixViscous::setmask() { int mask = 0; mask |= POST_FORCE; mask |= POST_FORCE_RESPA; mask |= MIN_POST_FORCE; return mask; } /* ---------------------------------------------------------------------- */ void FixViscous::init() { int max_respa = 0; if (strstr(update->integrate_style,"respa")) { ilevel_respa = max_respa = ((Respa *) update->integrate)->nlevels-1; if (respa_level >= 0) ilevel_respa = MIN(respa_level,max_respa); } } /* ---------------------------------------------------------------------- */ void FixViscous::setup(int vflag) { if (strstr(update->integrate_style,"verlet")) post_force(vflag); else { ((Respa *) update->integrate)->copy_flevel_f(ilevel_respa); post_force_respa(vflag,ilevel_respa,0); ((Respa *) update->integrate)->copy_f_flevel(ilevel_respa); } } /* ---------------------------------------------------------------------- */ void FixViscous::min_setup(int vflag) { post_force(vflag); } /* ---------------------------------------------------------------------- */ void FixViscous::post_force(int vflag) { // apply drag force to atoms in group // direction is opposed to velocity vector // magnitude depends on atom type double **v = atom->v; double **f = atom->f; int *mask = atom->mask; int *type = atom->type; int nlocal = atom->nlocal; double drag; for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { drag = gamma[type[i]]; f[i][0] -= drag*v[i][0]; f[i][1] -= drag*v[i][1]; f[i][2] -= drag*v[i][2]; } } /* ---------------------------------------------------------------------- */ void FixViscous::post_force_respa(int vflag, int ilevel, int iloop) { if (ilevel == ilevel_respa) post_force(vflag); } /* ---------------------------------------------------------------------- */ void FixViscous::min_post_force(int vflag) { post_force(vflag); }