diff --git a/src/LATTE/fix_latte.cpp b/src/LATTE/fix_latte.cpp index c6269f4c2..19a1e7860 100644 --- a/src/LATTE/fix_latte.cpp +++ b/src/LATTE/fix_latte.cpp @@ -1,331 +1,333 @@ /* ---------------------------------------------------------------------- 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. ------------------------------------------------------------------------- */ // NOTES on possible future issues: // LATTE compute and return 6-value virial tensor // can LATTE compute per-atom energy and per-atom virial // for minimize, what about charge DOFs // implement charge DOF integration // pass neighbor list to LATTE: half or full // will we ever auto-adjust the timestep in reset_dt() // could pass an input file to LATTE, specified in LAMMPS input script // what units options can LAMMPS be using // should LATTE take triclinic box from LAMMPS // does Coulomb potential = pe[i]/q[i], is it 0 when q = 0 // how will this work for serial/parallel LAMMPS with serial/parallel LATTE #include #include #include "fix_latte.h" #include "atom.h" #include "comm.h" #include "update.h" #include "neighbor.h" #include "domain.h" #include "force.h" #include "neigh_request.h" #include "neigh_list.h" #include "modify.h" #include "compute.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace FixConst; extern "C" { void latte(int *, int *, double *, int *, int *, - double *, double *, double *, double *, double *); + double *, double *, double *, double *, int*, double *, double *, double *); } #define INVOKED_PERATOM 8 /* ---------------------------------------------------------------------- */ FixLatte::FixLatte(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { if (narg != 4) error->all(FLERR,"Illegal fix latte command"); if (comm->nprocs != 1) error->all(FLERR,"Fix latte currently runs only in serial"); scalar_flag = 1; global_freq = 1; extscalar = 1; virial_flag = 1; // store ID of compute pe/atom used to generate Coulomb potential for LATTE // NULL means LATTE will compute Coulombic potential coulomb = 0; id_pe = NULL; if (strcmp(arg[3],"NULL") != 0) { coulomb = 1; int n = strlen(arg[3]) + 1; id_pe = new char[n]; strcpy(id_pe,arg[3]); int ipe = modify->find_compute(id_pe); if (ipe < 0) error->all(FLERR,"Could not find fix latte compute ID"); if (modify->compute[ipe]->peatomflag == 0) error->all(FLERR,"Fix latte compute ID does not compute pe/atom"); } // initializations nmax = 0; qpotential = NULL; flatte = NULL; latte_energy = 0.0; } /* ---------------------------------------------------------------------- */ FixLatte::~FixLatte() { delete [] id_pe; memory->destroy(qpotential); memory->destroy(flatte); } /* ---------------------------------------------------------------------- */ int FixLatte::setmask() { int mask = 0; //mask |= INITIAL_INTEGRATE; //mask |= FINAL_INTEGRATE; mask |= PRE_REVERSE; mask |= POST_FORCE; mask |= MIN_POST_FORCE; mask |= THERMO_ENERGY; return mask; } /* ---------------------------------------------------------------------- */ void FixLatte::init() { // error checks if (domain->dimension == 2) error->all(FLERR,"Fix latte requires 3d problem"); if (coulomb) { if (atom->q_flag == 0 || force->pair == NULL || force->kspace == NULL) error->all(FLERR,"Fix latte cannot compute Coulombic potential"); int ipe = modify->find_compute(id_pe); if (ipe < 0) error->all(FLERR,"Could not find fix latte compute ID"); c_pe = modify->compute[ipe]; } // must be fully periodic or fully non-periodic if (domain->nonperiodic == 0) pbcflag = 1; else if (!domain->xperiodic && !domain->yperiodic && !domain->zperiodic) pbcflag = 0; else error->all(FLERR,"Fix latte requires 3d simulation"); // create qpotential & flatte if needed // for now, assume nlocal will never change if (coulomb && qpotential == NULL) { memory->create(qpotential,atom->nlocal,"latte:qpotential"); memory->create(flatte,atom->nlocal,3,"latte:flatte"); } /* // warn if any integrate fix comes after this one // is it actually necessary for q(n) update to come after x,v update ?? int after = 0; int flag = 0; for (int i = 0; i < modify->nfix; i++) { if (strcmp(id,modify->fix[i]->id) == 0) after = 1; else if ((modify->fmask[i] & INITIAL_INTEGRATE) && after) flag = 1; } if (flag && comm->me == 0) error->warning(FLERR,"Fix latte should come after all other " "integration fixes"); */ /* // need a full neighbor list // could we use a half list? // perpetual list, built whenever re-neighboring occurs int irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->pair = 0; neighbor->requests[irequest]->fix = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->full = 1; */ } /* ---------------------------------------------------------------------- */ void FixLatte::init_list(int id, NeighList *ptr) { // list = ptr; } /* ---------------------------------------------------------------------- */ void FixLatte::setup(int vflag) { post_force(vflag); } /* ---------------------------------------------------------------------- */ void FixLatte::min_setup(int vflag) { post_force(vflag); } /* ---------------------------------------------------------------------- integrate electronic degrees of freedom ------------------------------------------------------------------------- */ void FixLatte::initial_integrate(int vflag) {} /* ---------------------------------------------------------------------- store eflag, so can use it in post_force to tally per-atom energies ------------------------------------------------------------------------- */ void FixLatte::pre_reverse(int eflag, int vflag) { eflag_caller = eflag; } /* ---------------------------------------------------------------------- */ void FixLatte::post_force(int vflag) { int eflag = eflag_caller; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; // compute Coulombic potential = pe[i]/q[i] // invoke compute pe/atom // wrap with clear/add and trigger pe/atom calculation every step if (coulomb) { modify->clearstep_compute(); if (!(c_pe->invoked_flag & INVOKED_PERATOM)) { c_pe->compute_peratom(); c_pe->invoked_flag |= INVOKED_PERATOM; } modify->addstep_compute(update->ntimestep+1); double *pe = c_pe->vector_atom; double *q = atom->q; int nlocal = atom->nlocal; for (int i = 0; i < nlocal; i++) if (q[i]) qpotential[i] = pe[i]/q[i]; else qpotential[i] = 0.0; } // hardwire these unsupported flags for now int coulombflag = 0; pe_peratom = 0; virial_global = 0; // set via vflag_global at some point virial_peratom = 0; neighflag = 0; // set flags used by LATTE int flags[6]; flags[0] = pbcflag; // 1 for fully periodic, 0 for fully non-periodic flags[1] = coulombflag; // 1 for LAMMPS computes Coulombics, 0 for LATTE flags[2] = pe_peratom; // 1 to return per-atom energies, 0 for no flags[3] = virial_global; // 1 to return global virial 0 for no flags[4] = virial_peratom; // 1 to return per-atom virial, 0 for no flags[5] = neighflag; // 1 to pass neighbor list to LATTE, 0 for no // setup LATTE arguments int natoms = atom->nlocal; double *coords = &atom->x[0][0]; int *type = atom->type; int ntypes = atom->ntypes; double *mass = &atom->mass[1]; double *boxlo = domain->boxlo; double *boxhi = domain->boxhi; double *forces; if (coulomb) forces = &flatte[0][0]; else forces = &atom->f[0][0]; // invoke LATTE + + int maxiter = -1; latte(flags,&natoms,coords,type,&ntypes,mass,boxlo,boxhi, - forces,&latte_energy); + forces,&maxiter, &latte_energy, &atom->v[0][0],&update->dt); // sum LATTE forces to LAMMPS (Coulombic) forces if (coulomb) { double **f = atom->f; int nlocal = atom->nlocal; for (int i = 0; i < nlocal; i++) { f[i][0] += flatte[i][0]; f[i][1] += flatte[i][1]; f[i][2] += flatte[i][2]; } } } /* ---------------------------------------------------------------------- integrate electronic degrees of freedom ------------------------------------------------------------------------- */ void FixLatte::final_integrate() {} /* ---------------------------------------------------------------------- */ void FixLatte::reset_dt() { //dtv = update->dt; //dtf = 0.5 * update->dt * force->ftm2v; } /* ---------------------------------------------------------------------- DFTB energy from LATTE ------------------------------------------------------------------------- */ double FixLatte::compute_scalar() { return latte_energy; } /* ---------------------------------------------------------------------- memory usage of local arrays ------------------------------------------------------------------------- */ double FixLatte::memory_usage() { double bytes = 0.0; if (coulomb) bytes += nmax * sizeof(double); if (coulomb) bytes += nmax*3 * sizeof(double); return bytes; }