/* ---------------------------------------------------------------------- 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: Ryan S. Elliott, Valeriu Smirichinski, Ellad Tadmor ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Designed for use with the kim-api-v1.6.0 (and newer) package ------------------------------------------------------------------------- */ #include #include // includes from LAMMPS #include "pair_kim.h" #include "atom.h" #include "comm.h" #include "force.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "update.h" #include "memory.h" #include "domain.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ PairKIM::PairKIM(LAMMPS *lmp) : Pair(lmp), settings_call_count(0), init_style_call_count(0), kim_modelname(0), lmps_map_species_to_unique(0), lmps_unique_elements(0), lmps_num_unique_elements(0), lmps_units(METAL), lengthUnit(KIM::LENGTH_UNIT::unused), energyUnit(KIM::ENERGY_UNIT::unused), chargeUnit(KIM::CHARGE_UNIT::unused), temperatureUnit(KIM::TEMPERATURE_UNIT::unused), timeUnit(KIM::TIME_UNIT::unused), pkim(0), pargs(0), kim_model_support_for_energy(KIM::SUPPORT_STATUS::notSupported), kim_model_support_for_forces(KIM::SUPPORT_STATUS::notSupported), kim_model_support_for_virial(KIM::SUPPORT_STATUS::notSupported), kim_model_support_for_particleEnergy(KIM::SUPPORT_STATUS::notSupported), kim_model_support_for_particleVirial(KIM::SUPPORT_STATUS::notSupported), lmps_local_tot_num_atoms(0), kim_global_influence_distance(0.0), kim_number_of_cutoffs(0), kim_cutoff_values(0), neighborLists(0), kim_particle_codes(0), lmps_maxalloc(0), kim_particleSpecies(0), kim_particleContributing(0), lmps_stripped_neigh_list(0), lmps_stripped_neigh_ptr(0) { // Initialize Pair data members to appropriate values single_enable = 0; // We do not provide the Single() function restartinfo = 0; // We do not write any restart info one_coeff = 1; // We only allow one coeff * * call // BEGIN: initial values that determine the KIM state // (used by kim_free(), etc.) kim_init_ok = false; kim_particle_codes_ok = false; // END return; } /* ---------------------------------------------------------------------- */ PairKIM::~PairKIM() { // clean up kim_modelname if (kim_modelname != 0) delete [] kim_modelname; // clean up lammps atom species number to unique particle names mapping if (lmps_unique_elements) for (int i = 0; i < lmps_num_unique_elements; i++) delete [] lmps_unique_elements[i]; delete [] lmps_unique_elements; // clean up local memory used to support KIM interface memory->destroy(kim_particleSpecies); memory->destroy(kim_particleContributing); memory->destroy(lmps_stripped_neigh_list); // clean up lmps_stripped_neigh_ptr if (lmps_stripped_neigh_ptr) { delete [] lmps_stripped_neigh_ptr; lmps_stripped_neigh_ptr = 0; } // clean up allocated memory for standard Pair class usage // also, we allocate lmps_map_species_to_uniuqe in the allocate() function if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); delete [] lmps_map_species_to_unique; } // clean up neighborlist pointers if (neighborLists) { delete [] neighborLists; neighborLists = 0; } // clean up KIM interface (if necessary) kim_free(); return; } /* ---------------------------------------------------------------------- */ void PairKIM::compute(int eflag , int vflag) { int kimerror; if (eflag || vflag) ev_setup(eflag,vflag); else ev_unset(); // grow kim_particleSpecies and kim_particleContributing array if necessary // needs to be atom->nmax in length if (atom->nmax > lmps_maxalloc) { memory->destroy(kim_particleSpecies); memory->destroy(kim_particleContributing); lmps_maxalloc = atom->nmax; memory->create(kim_particleSpecies,lmps_maxalloc, "pair:kim_particleSpecies"); int kimerror = pargs->SetArgumentPointer( KIM::COMPUTE_ARGUMENT_NAME::particleSpeciesCodes, kim_particleSpecies); memory->create(kim_particleContributing,lmps_maxalloc, "pair:kim_particleContributing"); kimerror = kimerror || pargs->SetArgumentPointer( KIM::COMPUTE_ARGUMENT_NAME::particleContributing, kim_particleContributing); if (kimerror) error->all( FLERR, "Unable to set KIM particle species codes and/or contributing"); } // kim_particleSpecies = KIM atom species for each LAMMPS atom int *species = atom->type; int nall = atom->nlocal + atom->nghost; int ielement; for (int i = 0; i < nall; i++) { ielement = lmps_map_species_to_unique[species[i]]; kim_particleSpecies[i] = kim_particle_codes[ielement]; kim_particleContributing[i] = ( (inlocal) ? 1 : 0 ); } // pass current atom pointers to KIM set_argument_pointers(); // set number of particles lmps_local_tot_num_atoms = (int) (atom->nghost + atom->nlocal); // compute via KIM model kimerror = pkim->Compute(pargs); if (kimerror) error->all(FLERR,"KIM Compute returned error"); // assemble force and particleVirial if needed if (!lmps_using_newton) comm->reverse_comm_pair(this); if ((no_virial_fdotr_compute == 1) && (vflag_global)) { // flip sign and order of virial if KIM is computing it for (int i = 0; i < 3; ++i) virial[i] = -1.0*virial[i]; double tmp = virial[3]; virial[3] = -virial[5]; virial[4] = -virial[4]; virial[5] = -tmp; } else { // compute virial via LAMMPS fdotr mechanism if (vflag_fdotr) virial_fdotr_compute(); } if ((kim_model_support_for_particleVirial != KIM::SUPPORT_STATUS::notSupported) && (vflag_atom)) { // flip sign and order of virial if KIM is computing it double tmp; for (int i = 0; i < nall; ++i) { for (int j = 0; j < 3; ++j) vatom[i][j] = -1.0*vatom[i][j]; tmp = vatom[i][3]; vatom[i][3] = -vatom[i][5]; vatom[i][4] = -vatom[i][4]; vatom[i][5] = -tmp; } } return; } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairKIM::allocate() { int n = atom->ntypes; // allocate standard Pair class arrays memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); // allocate mapping array lmps_map_species_to_unique = new int[n+1]; allocated = 1; return; } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairKIM::settings(int narg, char **arg) { // This is called when "pair_style kim ..." is read from input // may be called multiple times ++settings_call_count; init_style_call_count = 0; if (narg != 2) error->all(FLERR,"Illegal pair_style command"); // arg[0] is the virial handling option: "LAMMPSvirial" or "KIMvirial" // arg[1] is the KIM Model name lmps_using_molecular = (atom->molecular > 0); // ensure we are in a clean state for KIM (needed on repeated call) // first time called will do nothing... kim_free(); // make sure things are allocated if (allocated != 1) allocate(); // clear setflag to ensure coeff() is called after settings() int n = atom->ntypes; for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; // set lmps_* bool flags set_lmps_flags(); // set virial handling if (strcmp(arg[0],"LAMMPSvirial") == 0) { no_virial_fdotr_compute = 0; } else if (strcmp(arg[0],"KIMvirial") == 0) { no_virial_fdotr_compute = 1; } else { error->all(FLERR,"Unrecognized virial argument in pair_style command"); } // set KIM Model name int nmlen = strlen(arg[1]); if (kim_modelname != 0) { delete [] kim_modelname; kim_modelname = 0; } kim_modelname = new char[nmlen+1]; strcpy(kim_modelname, arg[1]); return; } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairKIM::coeff(int narg, char **arg) { // This is called when "pair_coeff ..." is read from input // may be called multiple times int i,j,n; if (!allocated) allocate(); if (narg != 2 + atom->ntypes) error->all(FLERR,"Incorrect args for pair coefficients"); // insure I,J args are * * if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0) error->all(FLERR,"Incorrect args for pair coefficients"); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); // read args that map atom species to KIM elements // lmps_map_species_to_unique[i] = // which element the Ith atom type is // lmps_num_unique_elements = # of unique elements // lmps_unique_elements = list of element names // if called multiple times: update lmps_unique_elements if (lmps_unique_elements) { for (i = 0; i < lmps_num_unique_elements; i++) delete [] lmps_unique_elements[i]; delete [] lmps_unique_elements; } lmps_unique_elements = new char*[atom->ntypes]; for (i = 0; i < atom->ntypes; i++) lmps_unique_elements[i] = 0; // Assume all species arguments are valid // errors will be detected by kim_api_init() matching lmps_num_unique_elements = 0; for (i = 2; i < narg; i++) { for (j = 0; j < lmps_num_unique_elements; j++) if (strcmp(arg[i],lmps_unique_elements[j]) == 0) break; lmps_map_species_to_unique[i-1] = j; if (j == lmps_num_unique_elements) { n = strlen(arg[i]) + 1; lmps_unique_elements[j] = new char[n]; strcpy(lmps_unique_elements[j],arg[i]); lmps_num_unique_elements++; } } int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { if (lmps_map_species_to_unique[i] >= 0 && lmps_map_species_to_unique[j] >= 0) { setflag[i][j] = 1; count++; } } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); return; } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairKIM::init_style() { // This is called for each "run ...", "minimize ...", etc. read from input ++init_style_call_count; if (domain->dimension != 3) error->all(FLERR,"PairKIM only works with 3D problems"); int kimerror; // KIM and Model initialization (only once) // also sets kim_ind_* and kim_* bool flags if (!kim_init_ok) { kim_init(); } // setup lmps_stripped_neigh_list for neighbors of one atom, if needed if (lmps_using_molecular) { memory->destroy(lmps_stripped_neigh_list); memory->create(lmps_stripped_neigh_list, kim_number_of_cutoffs*neighbor->oneatom, "pair:lmps_stripped_neigh_list"); delete [] lmps_stripped_neigh_ptr; lmps_stripped_neigh_ptr = new int*[kim_number_of_cutoffs]; for (int i = 0; i < kim_number_of_cutoffs; ++i) { lmps_stripped_neigh_ptr[0] = &(lmps_stripped_neigh_list[(i-1)*(neighbor->oneatom)]); } } // make sure comm_reverse expects (at most) 9 values when newton is off if (!lmps_using_newton) comm_reverse_off = 9; // request full neighbor lists for (int i = 0; i < kim_number_of_cutoffs; ++i) { int irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = i; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->full = 1; neighbor->requests[irequest]->ghost = 1; neighbor->requests[irequest]->cut = 1; neighbor->requests[irequest]->cutoff = kim_cutoff_values[i] + neighbor->skin; } return; } /* ---------------------------------------------------------------------- neighbor callback to inform pair style of neighbor list to use half or full ------------------------------------------------------------------------- */ void PairKIM::init_list(int id, NeighList *ptr) { neighborLists[id] = ptr; } /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairKIM::init_one(int i, int j) { // This is called once of each (unordered) i,j pair for each // "run ...", "minimize ...", etc. read from input if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set"); return kim_global_influence_distance; } /* ---------------------------------------------------------------------- */ int PairKIM::pack_reverse_comm(int n, int first, double *buf) { using namespace KIM::SUPPORT_STATUS; int i,m,last; double *fp; fp = &(atom->f[0][0]); m = 0; last = first + n; if ((kim_model_support_for_forces != notSupported) && ((vflag_atom == 0) || (kim_model_support_for_particleVirial == notSupported))) { for (i = first; i < last; i++) { buf[m++] = fp[3*i+0]; buf[m++] = fp[3*i+1]; buf[m++] = fp[3*i+2]; } return m; } else if ((kim_model_support_for_forces != notSupported) && (vflag_atom == 1) && (kim_model_support_for_particleVirial != notSupported)) { double *va=&(vatom[0][0]); for (i = first; i < last; i++) { buf[m++] = fp[3*i+0]; buf[m++] = fp[3*i+1]; buf[m++] = fp[3*i+2]; buf[m++] = va[6*i+0]; buf[m++] = va[6*i+1]; buf[m++] = va[6*i+2]; buf[m++] = va[6*i+3]; buf[m++] = va[6*i+4]; buf[m++] = va[6*i+5]; } return m; } else if ((kim_model_support_for_forces == notSupported) && (vflag_atom == 1) && (kim_model_support_for_particleVirial != notSupported)) { double *va=&(vatom[0][0]); for (i = first; i < last; i++) { buf[m++] = va[6*i+0]; buf[m++] = va[6*i+1]; buf[m++] = va[6*i+2]; buf[m++] = va[6*i+3]; buf[m++] = va[6*i+4]; buf[m++] = va[6*i+5]; } return m; } else return 0; } /* ---------------------------------------------------------------------- */ void PairKIM::unpack_reverse_comm(int n, int *list, double *buf) { using namespace KIM::SUPPORT_STATUS; int i,j,m; double *fp; fp = &(atom->f[0][0]); m = 0; if ((kim_model_support_for_forces != notSupported) && ((vflag_atom == 0) || (kim_model_support_for_particleVirial == notSupported))) { for (i = 0; i < n; i++) { j = list[i]; fp[3*j+0]+= buf[m++]; fp[3*j+1]+= buf[m++]; fp[3*j+2]+= buf[m++]; } } else if ((kim_model_support_for_forces != notSupported) && (vflag_atom == 1) && (kim_model_support_for_particleVirial != notSupported)) { double *va=&(vatom[0][0]); for (i = 0; i < n; i++) { j = list[i]; fp[3*j+0]+= buf[m++]; fp[3*j+1]+= buf[m++]; fp[3*j+2]+= buf[m++]; va[j*6+0]+=buf[m++]; va[j*6+1]+=buf[m++]; va[j*6+2]+=buf[m++]; va[j*6+3]+=buf[m++]; va[j*6+4]+=buf[m++]; va[j*6+5]+=buf[m++]; } } else if ((kim_model_support_for_forces == notSupported) && (vflag_atom == 1) && (kim_model_support_for_particleVirial != notSupported)) { double *va=&(vatom[0][0]); for (i = 0; i < n; i++) { j = list[i]; va[j*6+0]+=buf[m++]; va[j*6+1]+=buf[m++]; va[j*6+2]+=buf[m++]; va[j*6+3]+=buf[m++]; va[j*6+4]+=buf[m++]; va[j*6+5]+=buf[m++]; } } else ;// do nothing return; } /* ---------------------------------------------------------------------- memory usage of local atom-based arrays ------------------------------------------------------------------------- */ double PairKIM::memory_usage() { double bytes = 2 * lmps_maxalloc * sizeof(int); return bytes; } /* ---------------------------------------------------------------------- KIM-specific interface ------------------------------------------------------------------------- */ int PairKIM::get_neigh(void const * const dataObject, int const numberOfCutoffs, double const * const cutoffs, int const neighborListIndex, int const particleNumber, int * const numberOfNeighbors, int const ** const neighborsOfParticle) { PairKIM const * const Model = reinterpret_cast(dataObject); if (numberOfCutoffs != Model->kim_number_of_cutoffs) return true; for (int i = 0; i < numberOfCutoffs; ++i) { if (Model->kim_cutoff_values[i] < cutoffs[i]) return true; } // neighborListIndex and particleNumber are validated by KIM API // initialize numNeigh *numberOfNeighbors = 0; NeighList * neiobj = Model->neighborLists[neighborListIndex]; int nAtoms = Model->lmps_local_tot_num_atoms; int j, jj, inum, *ilist, *numneigh, **firstneigh; inum = neiobj->inum; //# of I atoms neighbors are stored for ilist = neiobj->ilist; //local indices of I atoms numneigh = neiobj->numneigh; // # of J neighbors for each I atom firstneigh = neiobj->firstneigh; // ptr to 1st J int value of each I atom *numberOfNeighbors = numneigh[particleNumber]; // strip off neighbor mask for molecular systems if (!Model->lmps_using_molecular) *neighborsOfParticle = firstneigh[particleNumber]; else { int n = *numberOfNeighbors; int *ptr = firstneigh[particleNumber]; int *lmps_stripped_neigh_list = Model->lmps_stripped_neigh_ptr[neighborListIndex]; for (int i = 0; i < n; i++) lmps_stripped_neigh_list[i] = *(ptr++) & NEIGHMASK; *neighborsOfParticle = lmps_stripped_neigh_list; } return false; } /* ---------------------------------------------------------------------- */ void PairKIM::kim_free() { int kimerror; if (kim_init_ok) { int kimerror = pkim->ComputeArgumentsDestroy(&pargs); if (kimerror) error->all(FLERR,"Unable to destroy Compute Arguments Object"); KIM::Model::Destroy(&pkim); } kim_init_ok = false; if (kim_particle_codes_ok) { delete [] kim_particle_codes; kim_particle_codes = 0; kim_particle_codes_ok = false; } return; } /* ---------------------------------------------------------------------- */ void PairKIM::kim_init() { int kimerror; // initialize KIM model int requestedUnitsAccepted; kimerror = KIM::Model::Create( KIM::NUMBERING::zeroBased, lengthUnit, energyUnit, chargeUnit, temperatureUnit, timeUnit, kim_modelname, &requestedUnitsAccepted, &pkim); if (kimerror) error->all(FLERR,"KIM ModelCreate failed"); else { if (!requestedUnitsAccepted) { // @@@ error for now. Fix as needed error->all(FLERR,"KIM Model did not accept the requested unit system"); } kimerror = pkim->ComputeArgumentsCreate(&pargs); if (kimerror) { KIM::Model::Destroy(&pkim); error->all(FLERR,"KIM ComputeArgumentsCreate failed"); } else { kim_init_ok = true; } } // determine KIM Model capabilities (used in this function below) set_kim_model_has_flags(); // setup mapping between LAMMPS unique elements and KIM species codes kim_particle_codes = new int[lmps_num_unique_elements]; kim_particle_codes_ok = true; for(int i = 0; i < lmps_num_unique_elements; i++){ int kimerror; int supported; int code; kimerror = pkim->GetSpeciesSupportAndCode( KIM::SpeciesName(lmps_unique_elements[i]), &supported, &code); if (supported) kim_particle_codes[i] = code; else error->all(FLERR,"create_kim_particle_codes: symbol not found "); } pkim->GetInfluenceDistance(&kim_global_influence_distance); pkim->GetNeighborListCutoffsPointer(&kim_number_of_cutoffs, &kim_cutoff_values); if (neighborLists) { delete [] neighborLists; neighborLists = 0; } neighborLists = new NeighList*[kim_number_of_cutoffs]; kimerror = pargs->SetArgumentPointer( KIM::COMPUTE_ARGUMENT_NAME::numberOfParticles, &lmps_local_tot_num_atoms); if (kim_model_support_for_energy != KIM::SUPPORT_STATUS::notSupported) kimerror = kimerror || pargs->SetArgumentPointer( KIM::COMPUTE_ARGUMENT_NAME::partialEnergy, &(eng_vdwl)); kimerror = pargs->SetCallbackPointer( KIM::COMPUTE_CALLBACK_NAME::GetNeighborList, KIM::LANGUAGE_NAME::cpp, reinterpret_cast(get_neigh), reinterpret_cast(this)); if (kimerror) error->all(FLERR,"Unable to register KIM pointers"); return; } /* ---------------------------------------------------------------------- */ void PairKIM::set_argument_pointers() { using namespace KIM::COMPUTE_ARGUMENT_NAME; using namespace KIM::SUPPORT_STATUS; int kimerror; kimerror = pargs->SetArgumentPointer(coordinates, &(atom->x[0][0])); // Set KIM pointer appropriately for particalEnergy if ((kim_model_support_for_particleEnergy == required) && (eflag_atom != 1)) { // reallocate per-atom energy array if necessary if (atom->nmax > maxeatom) { maxeatom = atom->nmax; memory->destroy(eatom); memory->create(eatom,comm->nthreads*maxeatom,"pair:eatom"); } } if ((kim_model_support_for_particleEnergy == optional) && (eflag_atom != 1)) { kimerror = kimerror || pargs->SetArgumentPointer( partialParticleEnergy, reinterpret_cast(NULL)); } else if (kim_model_support_for_particleEnergy != notSupported) { kimerror = kimerror || pargs->SetArgumentPointer(partialParticleEnergy, eatom); } // Set KIM pointer appropriately for forces if (kim_model_support_for_forces == notSupported) { kimerror = kimerror || pargs->SetArgumentPointer( partialForces, reinterpret_cast(NULL)); } else { kimerror = kimerror || pargs->SetArgumentPointer(partialForces, &(atom->f[0][0])); } // Set KIM pointer appropriately for particleVirial if ((kim_model_support_for_particleVirial == required) && (vflag_atom != 1)) { // reallocate per-atom virial array if necessary if (atom->nmax > maxeatom) { maxvatom = atom->nmax; memory->destroy(vatom); memory->create(vatom,comm->nthreads*maxvatom,6,"pair:vatom"); } } if ((kim_model_support_for_particleVirial == optional) && (vflag_atom != 1)) { kimerror = kimerror || pargs->SetArgumentPointer( partialParticleVirial, reinterpret_cast(NULL)); } else if (kim_model_support_for_particleVirial != notSupported) { kimerror = kimerror || pargs->SetArgumentPointer(partialParticleEnergy, &(vatom[0][0])); } // Set KIM pointer appropriately for virial if (kim_model_support_for_virial == required) { kimerror = kimerror || pargs->SetArgumentPointer(partialVirial, &(virial[0])); } else if ((kim_model_support_for_virial == optional) && (no_virial_fdotr_compute == 1) && (vflag_global)) { kimerror = kimerror || pargs->SetArgumentPointer(partialVirial, &(virial[0])); } else if (kim_model_support_for_virial == optional) { kimerror = kimerror || pargs->SetArgumentPointer( partialVirial, reinterpret_cast(NULL)); } if (kimerror) { error->all(FLERR,"Unable to set KIM argument pointers"); } return; } /* ---------------------------------------------------------------------- */ void PairKIM::set_lmps_flags() { // determint if newton is on or off lmps_using_newton = (force->newton_pair == 1); // determine if running with pair hybrid if (force->pair_match("hybrid",0)) { error->all(FLERR,"pair_kim does not support hybrid."); } // determine unit system and set lmps_units flag if ((strcmp(update->unit_style,"real")==0)) { lmps_units = REAL; lengthUnit = KIM::LENGTH_UNIT::A; energyUnit = KIM::ENERGY_UNIT::kcal_mol; chargeUnit = KIM::CHARGE_UNIT::e; temperatureUnit = KIM::TEMPERATURE_UNIT::K; timeUnit = KIM::TIME_UNIT::fs; } else if ((strcmp(update->unit_style,"metal")==0)) { lmps_units = METAL; lengthUnit = KIM::LENGTH_UNIT::A; energyUnit = KIM::ENERGY_UNIT::eV; chargeUnit = KIM::CHARGE_UNIT::e; temperatureUnit = KIM::TEMPERATURE_UNIT::K; timeUnit = KIM::TIME_UNIT::ps; } else if ((strcmp(update->unit_style,"si")==0)) { lmps_units = SI; lengthUnit = KIM::LENGTH_UNIT::m; energyUnit = KIM::ENERGY_UNIT::J; chargeUnit = KIM::CHARGE_UNIT::C; temperatureUnit = KIM::TEMPERATURE_UNIT::K; timeUnit = KIM::TIME_UNIT::s; } else if ((strcmp(update->unit_style,"cgs")==0)) { lmps_units = CGS; lengthUnit = KIM::LENGTH_UNIT::cm; energyUnit = KIM::ENERGY_UNIT::erg; chargeUnit = KIM::CHARGE_UNIT::statC; temperatureUnit = KIM::TEMPERATURE_UNIT::K; timeUnit = KIM::TIME_UNIT::s; } else if ((strcmp(update->unit_style,"electron")==0)) { lmps_units = ELECTRON; lengthUnit = KIM::LENGTH_UNIT::Bohr; energyUnit = KIM::ENERGY_UNIT::Hartree; chargeUnit = KIM::CHARGE_UNIT::e; temperatureUnit = KIM::TEMPERATURE_UNIT::K; timeUnit = KIM::TIME_UNIT::fs; } else if ((strcmp(update->unit_style,"lj")==0)) { error->all(FLERR,"LAMMPS unit_style lj not supported by KIM models"); } else { error->all(FLERR,"Unknown unit_style"); } return; } /* ---------------------------------------------------------------------- */ void PairKIM::set_kim_model_has_flags() { { // BEGIN enclosing scope for using directives using namespace KIM::COMPUTE_ARGUMENT_NAME; using namespace KIM::SUPPORT_STATUS; int numberOfComputeArgumentNames; GetNumberOfComputeArgumentNames(&numberOfComputeArgumentNames); for (int i = 0; i < numberOfComputeArgumentNames; ++i) { KIM::ComputeArgumentName computeArgumentName; int kimerror = GetComputeArgumentName(i, &computeArgumentName); KIM::SupportStatus supportStatus; kimerror = pargs->GetArgumentSupportStatus(computeArgumentName, &supportStatus); if (computeArgumentName == partialEnergy) kim_model_support_for_energy = supportStatus; else if (computeArgumentName == partialForces) kim_model_support_for_forces = supportStatus; else if (computeArgumentName == partialVirial) kim_model_support_for_virial = supportStatus; else if (computeArgumentName == partialParticleEnergy) kim_model_support_for_particleEnergy = supportStatus; else if (computeArgumentName == partialParticleVirial) kim_model_support_for_particleVirial = supportStatus; else if (supportStatus == required) { error->all(FLERR,"KIM Model requires unsupported compute argument"); } } if (kim_model_support_for_energy == notSupported) error->warning(FLERR,"KIM Model does not provide `partialEnergy'; " "Potential energy will be zero"); if (kim_model_support_for_forces == notSupported) error->warning(FLERR,"KIM Model does not provide `partialForce'; " "Forces will be zero"); if ((no_virial_fdotr_compute == 1) && (kim_model_support_for_virial == notSupported)) { error->warning(FLERR,"KIM Model does not provide `partialVirial'. " "pair_kim now using `LAMMPSvirial' option."); no_virial_fdotr_compute = 0; } if (kim_model_support_for_particleEnergy == notSupported) error->warning(FLERR,"KIM Model does not provide `partialParticleEnergy'; " "energy per atom will be zero"); if (kim_model_support_for_particleVirial == notSupported) error->warning(FLERR,"KIM Model does not provide `partialParticleVirial'; " "virial per atom will be zero"); } // END enclosing scope for using directives { // BEGIN enclosing scope for using directives using namespace KIM::COMPUTE_CALLBACK_NAME; using namespace KIM::SUPPORT_STATUS; int numberOfComputeCallbackNames; GetNumberOfComputeCallbackNames(&numberOfComputeCallbackNames); for (int i = 0; i < numberOfComputeCallbackNames; ++i) { KIM::ComputeCallbackName computeCallbackName; int kimerror = GetComputeCallbackName(i, &computeCallbackName); KIM::SupportStatus supportStatus; kimerror = pargs->GetCallbackSupportStatus(computeCallbackName, &supportStatus); if (supportStatus == required) { error->all(FLERR,"KIM Model requires unsupported compute callback"); } } } // END enclosing scope for using directives return; }