/* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://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 "fix_langevin_kokkos.h" #include "atom_kokkos.h" #include "atom_masks.h" #include "comm.h" #include "compute.h" #include "error.h" #include "force.h" #include "group.h" #include "input.h" #include "memory_kokkos.h" #include "modify.h" #include "update.h" #include "variable.h" #include using namespace LAMMPS_NS; using namespace FixConst; enum{NOBIAS,BIAS}; enum{CONSTANT,EQUAL,ATOM}; #define SINERTIA 0.4 // moment of inertia prefactor for sphere #define EINERTIA 0.2 // moment of inertia prefactor for ellipsoid /* ---------------------------------------------------------------------- */ template FixLangevinKokkos::FixLangevinKokkos(LAMMPS *lmp, int narg, char **arg) : FixLangevin(lmp, narg, arg),rand_pool(seed + comm->me) { kokkosable = 1; atomKK = (AtomKokkos *) atom; int ntypes = atomKK->ntypes; // allocate per-type arrays for force prefactors memoryKK->create_kokkos(k_gfactor1,gfactor1,ntypes+1,"langevin:gfactor1"); memoryKK->create_kokkos(k_gfactor2,gfactor2,ntypes+1,"langevin:gfactor2"); memoryKK->create_kokkos(k_ratio,ratio,ntypes+1,"langevin:ratio"); d_gfactor1 = k_gfactor1.template view(); h_gfactor1 = k_gfactor1.template view(); d_gfactor2 = k_gfactor2.template view(); h_gfactor2 = k_gfactor2.template view(); d_ratio = k_ratio.template view(); h_ratio = k_ratio.template view(); // optional args for (int i = 1; i <= ntypes; i++) ratio[i] = 1.0; k_ratio.template modify(); if (gjfflag) { grow_arrays(atomKK->nmax); atom->add_callback(Atom::GROW); // initialize franprev to zero for (int i = 0; i < atomKK->nlocal; i++) { franprev[i][0] = 0.0; franprev[i][1] = 0.0; franprev[i][2] = 0.0; lv[i][0] = 0.0; lv[i][1] = 0.0; lv[i][2] = 0.0; } k_franprev.template modify(); k_lv.template modify(); } if (zeroflag) { k_fsumall = tdual_double_1d_3n("langevin:fsumall"); h_fsumall = k_fsumall.template view(); d_fsumall = k_fsumall.template view(); } execution_space = ExecutionSpaceFromDevice::space; datamask_read = V_MASK | F_MASK | MASK_MASK | RMASS_MASK | TYPE_MASK; datamask_modify = F_MASK; } /* ---------------------------------------------------------------------- */ template FixLangevinKokkos::~FixLangevinKokkos() { memoryKK->destroy_kokkos(k_gfactor1,gfactor1); memoryKK->destroy_kokkos(k_gfactor2,gfactor2); memoryKK->destroy_kokkos(k_ratio,ratio); memoryKK->destroy_kokkos(k_flangevin,flangevin); if (gjfflag) memoryKK->destroy_kokkos(k_franprev,franprev); if (gjfflag) memoryKK->destroy_kokkos(k_lv,lv); memoryKK->destroy_kokkos(k_tforce,tforce); } /* ---------------------------------------------------------------------- */ template void FixLangevinKokkos::init() { FixLangevin::init(); if (oflag) error->all(FLERR,"Fix langevin omega is not yet implemented with kokkos"); if (ascale) error->all(FLERR,"Fix langevin angmom is not yet implemented with kokkos"); if (gjfflag && tbiasflag) error->all(FLERR,"Fix langevin gjf + tbias is not yet implemented with kokkos"); if (gjfflag && tbiasflag) error->warning(FLERR,"Fix langevin gjf + kokkos is not implemented with random gaussians"); // prefactors are modified in the init k_gfactor1.template modify(); k_gfactor2.template modify(); } /* ---------------------------------------------------------------------- */ template void FixLangevinKokkos::grow_arrays(int nmax) { memoryKK->grow_kokkos(k_franprev,franprev,nmax,3,"langevin:franprev"); d_franprev = k_franprev.template view(); h_franprev = k_franprev.template view(); memoryKK->grow_kokkos(k_lv,lv,nmax,3,"langevin:lv"); d_lv = k_lv.template view(); h_lv = k_lv.template view(); } /* ---------------------------------------------------------------------- */ template void FixLangevinKokkos::initial_integrate(int /*vflag*/) { atomKK->sync(execution_space,datamask_read); atomKK->modified(execution_space,datamask_modify); v = atomKK->k_v.view(); f = atomKK->k_f.view(); int nlocal = atomKK->nlocal; if (igroup == atomKK->firstgroup) nlocal = atomKK->nfirst; FixLangevinKokkosInitialIntegrateFunctor functor(this); Kokkos::parallel_for(nlocal,functor); } template KOKKOS_INLINE_FUNCTION void FixLangevinKokkos::initial_integrate_item(int i) const { if (mask[i] & groupbit) { f(i,0) /= gjfa; f(i,1) /= gjfa; f(i,2) /= gjfa; v(i,0) = d_lv(i,0); v(i,1) = d_lv(i,1); v(i,2) = d_lv(i,2); } } /* ---------------------------------------------------------------------- */ template void FixLangevinKokkos::post_force(int /*vflag*/) { // sync the device views which might have been modified on host atomKK->sync(execution_space,datamask_read); rmass = atomKK->k_rmass.view(); f = atomKK->k_f.template view(); v = atomKK->k_v.template view(); type = atomKK->k_type.template view(); mask = atomKK->k_mask.template view(); k_gfactor1.template sync(); k_gfactor2.template sync(); k_ratio.template sync(); if (gjfflag) k_franprev.template sync(); if (gjfflag) k_lv.template sync(); boltz = force->boltz; dt = update->dt; mvv2e = force->mvv2e; ftm2v = force->ftm2v; fran_prop_const = sqrt(24.0*boltz/t_period/dt/mvv2e); compute_target(); // modifies tforce vector, hence sync here k_tforce.template sync(); double fsum[3],fsumall[3]; bigint count; int nlocal = atomKK->nlocal; if (zeroflag) { fsum[0] = fsum[1] = fsum[2] = 0.0; count = group->count(igroup); if (count == 0) error->all(FLERR,"Cannot zero Langevin force of 0 atoms"); } // reallocate flangevin if necessary if (tallyflag || osflag) { if (nlocal > maxatom1) { memoryKK->destroy_kokkos(k_flangevin,flangevin); maxatom1 = atomKK->nmax; memoryKK->create_kokkos(k_flangevin,flangevin,maxatom1,3,"langevin:flangevin"); d_flangevin = k_flangevin.template view(); h_flangevin = k_flangevin.template view(); } } // account for bias velocity if (tbiasflag == BIAS) { atomKK->sync(temperature->execution_space,temperature->datamask_read); temperature->compute_scalar(); temperature->remove_bias_all(); // modifies velocities // if temeprature compute is kokkosized host-device comm won't be needed atomKK->modified(temperature->execution_space,temperature->datamask_modify); atomKK->sync(execution_space,temperature->datamask_modify); } // compute langevin force in parallel on the device FSUM s_fsum; if (tstyle == ATOM) if (gjfflag) if (tallyflag || osflag) if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (tallyflag || osflag) if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (gjfflag) if (tallyflag || osflag) if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (tallyflag || osflag) if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (tbiasflag == BIAS) if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (rmass.data()) if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } else if (zeroflag) { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_reduce(nlocal,post_functor,s_fsum); } else { FixLangevinKokkosPostForceFunctor post_functor(this); Kokkos::parallel_for(nlocal,post_functor); } if (tbiasflag == BIAS) { atomKK->sync(temperature->execution_space,temperature->datamask_read); temperature->restore_bias_all(); // modifies velocities atomKK->modified(temperature->execution_space,temperature->datamask_modify); atomKK->sync(execution_space,temperature->datamask_modify); } // set modify flags for the views modified in post_force functor if (gjfflag) k_franprev.template modify(); if (gjfflag) k_lv.template modify(); if (tallyflag || osflag) k_flangevin.template modify(); // set total force to zero if (zeroflag) { fsum[0] = s_fsum.fx; fsum[1] = s_fsum.fy; fsum[2] = s_fsum.fz; MPI_Allreduce(fsum,fsumall,3,MPI_DOUBLE,MPI_SUM,world); h_fsumall(0) = fsumall[0]/count; h_fsumall(1) = fsumall[1]/count; h_fsumall(2) = fsumall[2]/count; k_fsumall.template modify(); k_fsumall.template sync(); // set total force zero in parallel on the device FixLangevinKokkosZeroForceFunctor zero_functor(this); Kokkos::parallel_for(nlocal,zero_functor); } // f is modified by both post_force and zero_force functors atomKK->modified(execution_space,datamask_modify); // thermostat omega and angmom // if (oflag) omega_thermostat(); // if (ascale) angmom_thermostat(); } /* ---------------------------------------------------------------------- */ template template KOKKOS_INLINE_FUNCTION FSUM FixLangevinKokkos::post_force_item(int i) const { FSUM fsum; double fdrag[3],fran[3]; double gamma1,gamma2; double fswap; double tsqrt_t = tsqrt; if (mask[i] & groupbit) { rand_type rand_gen = rand_pool.get_state(); if (Tp_TSTYLEATOM) tsqrt_t = sqrt(d_tforce[i]); if (Tp_RMASS) { gamma1 = -rmass[i] / t_period / ftm2v; gamma2 = sqrt(rmass[i]) * fran_prop_const / ftm2v; gamma1 *= 1.0/d_ratio[type[i]]; gamma2 *= 1.0/sqrt(d_ratio[type[i]]) * tsqrt_t; } else { gamma1 = d_gfactor1[type[i]]; gamma2 = d_gfactor2[type[i]] * tsqrt_t; } fran[0] = gamma2 * (rand_gen.drand() - 0.5); //(random->uniform()-0.5); fran[1] = gamma2 * (rand_gen.drand() - 0.5); //(random->uniform()-0.5); fran[2] = gamma2 * (rand_gen.drand() - 0.5); //(random->uniform()-0.5); if (Tp_BIAS) { fdrag[0] = gamma1*v(i,0); fdrag[1] = gamma1*v(i,1); fdrag[2] = gamma1*v(i,2); if (v(i,0) == 0.0) fran[0] = 0.0; if (v(i,1) == 0.0) fran[1] = 0.0; if (v(i,2) == 0.0) fran[2] = 0.0; } else { fdrag[0] = gamma1*v(i,0); fdrag[1] = gamma1*v(i,1); fdrag[2] = gamma1*v(i,2); } if (Tp_GJF) { d_lv(i,0) = gjfsib*v(i,0); d_lv(i,1) = gjfsib*v(i,1); d_lv(i,2) = gjfsib*v(i,2); fswap = 0.5*(fran[0]+d_franprev(i,0)); d_franprev(i,0) = fran[0]; fran[0] = fswap; fswap = 0.5*(fran[1]+d_franprev(i,1)); d_franprev(i,1) = fran[1]; fran[1] = fswap; fswap = 0.5*(fran[2]+d_franprev(i,2)); d_franprev(i,2) = fran[2]; fran[2] = fswap; fdrag[0] *= gjfa; fdrag[1] *= gjfa; fdrag[2] *= gjfa; fran[0] *= gjfa; fran[1] *= gjfa; fran[2] *= gjfa; f(i,0) *= gjfa; f(i,1) *= gjfa; f(i,2) *= gjfa; } f(i,0) += fdrag[0] + fran[0]; f(i,1) += fdrag[1] + fran[1]; f(i,2) += fdrag[2] + fran[2]; if (Tp_TALLY) { if (Tp_GJF) { fdrag[0] = gamma1*d_lv(i,0)/gjfsib/gjfsib; fdrag[1] = gamma1*d_lv(i,1)/gjfsib/gjfsib; fdrag[2] = gamma1*d_lv(i,2)/gjfsib/gjfsib; fswap = (2*fran[0]/gjfa - d_franprev(i,0))/gjfsib; fran[0] = fswap; fswap = (2*fran[1]/gjfa - d_franprev(i,1))/gjfsib; fran[1] = fswap; fswap = (2*fran[2]/gjfa - d_franprev(i,2))/gjfsib; fran[2] = fswap; } d_flangevin(i,0) = fdrag[0] + fran[0]; d_flangevin(i,1) = fdrag[1] + fran[1]; d_flangevin(i,2) = fdrag[2] + fran[2]; } if (Tp_ZERO) { fsum.fx = fran[0]; fsum.fy = fran[1]; fsum.fz = fran[2]; } rand_pool.free_state(rand_gen); } return fsum; } /* ---------------------------------------------------------------------- */ template KOKKOS_INLINE_FUNCTION void FixLangevinKokkos::zero_force_item(int i) const { if (mask[i] & groupbit) { f(i,0) -= d_fsumall[0]; f(i,1) -= d_fsumall[1]; f(i,2) -= d_fsumall[2]; } } /* ---------------------------------------------------------------------- set current t_target and t_sqrt ------------------------------------------------------------------------- */ template void FixLangevinKokkos::compute_target() { atomKK->sync(Host, MASK_MASK); mask = atomKK->k_mask.template view(); int nlocal = atomKK->nlocal; double delta = update->ntimestep - update->beginstep; if (delta != 0.0) delta /= update->endstep - update->beginstep; // if variable temp, evaluate variable, wrap with clear/add // reallocate tforce array if necessary if (tstyle == CONSTANT) { t_target = t_start + delta * (t_stop-t_start); tsqrt = sqrt(t_target); } else { modify->clearstep_compute(); if (tstyle == EQUAL) { t_target = input->variable->compute_equal(tvar); if (t_target < 0.0) error->one(FLERR,"Fix langevin variable returned negative temperature"); tsqrt = sqrt(t_target); } else { if (atom->nmax > maxatom2) { maxatom2 = atom->nmax; memoryKK->destroy_kokkos(k_tforce,tforce); memoryKK->create_kokkos(k_tforce,tforce,maxatom2,"langevin:tforce"); d_tforce = k_tforce.template view(); h_tforce = k_tforce.template view(); } input->variable->compute_atom(tvar,igroup,tforce,1,0); // tforce is modified on host k_tforce.template modify(); for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) if (h_tforce[i] < 0.0) error->one(FLERR, "Fix langevin variable returned negative temperature"); } modify->addstep_compute(update->ntimestep + 1); } } /* ---------------------------------------------------------------------- */ template void FixLangevinKokkos::reset_dt() { if (atomKK->mass) { for (int i = 1; i <= atomKK->ntypes; i++) { h_gfactor2[i] = sqrt(atomKK->mass[i]) * sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) / force->ftm2v; h_gfactor2[i] *= 1.0/sqrt(h_ratio[i]); } k_gfactor2.template modify(); } } /* ---------------------------------------------------------------------- */ template double FixLangevinKokkos::compute_scalar() { if (!tallyflag || flangevin == nullptr) return 0.0; v = atomKK->k_v.template view(); mask = atomKK->k_mask.template view(); // capture the very first energy transfer to thermal reservoir if (update->ntimestep == update->beginstep) { energy_onestep = 0.0; atomKK->sync(execution_space,V_MASK | MASK_MASK); int nlocal = atomKK->nlocal; k_flangevin.template sync(); FixLangevinKokkosTallyEnergyFunctor scalar_functor(this); Kokkos::parallel_reduce(nlocal,scalar_functor,energy_onestep); energy = 0.5*energy_onestep*update->dt; } // convert midstep energy back to previous fullstep energy double energy_me = energy - 0.5*energy_onestep*update->dt; double energy_all; MPI_Allreduce(&energy_me,&energy_all,1,MPI_DOUBLE,MPI_SUM,world); return -energy_all; } /* ---------------------------------------------------------------------- */ template KOKKOS_INLINE_FUNCTION double FixLangevinKokkos::compute_energy_item(int i) const { double my_energy = 0.0; if (mask[i] & groupbit) my_energy = d_flangevin(i,0)*v(i,0) + d_flangevin(i,1)*v(i,1) + d_flangevin(i,2)*v(i,2); return my_energy; } /* ---------------------------------------------------------------------- tally energy transfer to thermal reservoir ------------------------------------------------------------------------- */ template void FixLangevinKokkos::end_of_step() { if (!tallyflag && !gjfflag) return; v = atomKK->k_v.template view(); f = atomKK->k_f.template view(); mask = atomKK->k_mask.template view(); atomKK->sync(execution_space,V_MASK | MASK_MASK); int nlocal = atomKK->nlocal; energy_onestep = 0.0; k_flangevin.template sync(); FixLangevinKokkosTallyEnergyFunctor tally_functor(this); Kokkos::parallel_reduce(nlocal,tally_functor,energy_onestep); if (gjfflag) { if (rmass.data()) { FixLangevinKokkosEndOfStepFunctor functor(this); Kokkos::parallel_for(nlocal,functor); } else { mass = atomKK->k_mass.view(); FixLangevinKokkosEndOfStepFunctor functor(this); Kokkos::parallel_for(nlocal,functor); } } energy += energy_onestep*update->dt; } template KOKKOS_INLINE_FUNCTION void FixLangevinKokkos::end_of_step_item(int i) const { double tmp[3]; if (mask[i] & groupbit) { const double dtfm = force->ftm2v * 0.5 * dt / mass[type[i]]; tmp[0] = v(i,0); tmp[1] = v(i,1); tmp[2] = v(i,2); if (!osflag) { v(i,0) = d_lv(i,0); v(i,1) = d_lv(i,1); v(i,2) = d_lv(i,2); } else { v(i,0) = 0.5 * gjfsib * gjfsib * (v(i,0) + dtfm * f(i,0) / gjfa) + dtfm * 0.5 * (gjfsib * d_flangevin(i,0) - d_franprev(i,0)) + (gjfsib * gjfa * 0.5 + dt * 0.25 / t_period / gjfsib) * d_lv(i,0); v(i,1) = 0.5 * gjfsib * gjfsib * (v(i,1) + dtfm * f(i,1) / gjfa) + dtfm * 0.5 * (gjfsib * d_flangevin(i,0) - d_franprev(i,1)) + (gjfsib * gjfa * 0.5 + dt * 0.25 / t_period / gjfsib) * d_lv(i,1); v(i,2) = 0.5 * gjfsib * gjfsib * (v(i,2) + dtfm * f(i,2) / gjfa) + dtfm * 0.5 * (gjfsib * d_flangevin(i,0) - d_franprev(i,2)) + (gjfsib * gjfa * 0.5 + dt * 0.25 / t_period / gjfsib) * d_lv(i,2); } d_lv(i,0) = tmp[0]; d_lv(i,1) = tmp[1]; d_lv(i,2) = tmp[2]; } } template KOKKOS_INLINE_FUNCTION void FixLangevinKokkos::end_of_step_rmass_item(int i) const { double tmp[3]; if (mask[i] & groupbit) { const double dtfm = force->ftm2v * 0.5 * dt / rmass[i]; tmp[0] = v(i,0); tmp[1] = v(i,1); tmp[2] = v(i,2); if (!osflag) { v(i,0) = d_lv(i,0); v(i,1) = d_lv(i,1); v(i,2) = d_lv(i,2); } else { v(i,0) = 0.5 * gjfsib * gjfsib * (v(i,0) + dtfm * f(i,0) / gjfa) + dtfm * 0.5 * (gjfsib * d_flangevin(i,0) - d_franprev(i,0)) + (gjfsib * gjfa * 0.5 + dt * 0.25 / t_period / gjfsib) * d_lv(i,0); v(i,1) = 0.5 * gjfsib * gjfsib * (v(i,1) + dtfm * f(i,1) / gjfa) + dtfm * 0.5 * (gjfsib * d_flangevin(i,1) - d_franprev(i,1)) + (gjfsib * gjfa * 0.5 + dt * 0.25 / t_period / gjfsib) * d_lv(i,1); v(i,2) = 0.5 * gjfsib * gjfsib * (v(i,2) + dtfm * f(i,2) / gjfa) + dtfm * 0.5 * (gjfsib * d_flangevin(i,2) - d_franprev(i,2)) + (gjfsib * gjfa * 0.5 + dt * 0.25 / t_period / gjfsib) * d_lv(i,2); } d_lv(i,0) = tmp[0]; d_lv(i,1) = tmp[1]; d_lv(i,2) = tmp[2]; } } /* ---------------------------------------------------------------------- copy values within local atom-based array ------------------------------------------------------------------------- */ template void FixLangevinKokkos::copy_arrays(int i, int j, int /*delflag*/) { h_franprev(j,0) = h_franprev(i,0); h_franprev(j,1) = h_franprev(i,1); h_franprev(j,2) = h_franprev(i,2); h_lv(j,0) = h_lv(i,0); h_lv(j,1) = h_lv(i,1); h_lv(j,2) = h_lv(i,2); k_franprev.template modify(); k_lv.template modify(); } /* ---------------------------------------------------------------------- */ template void FixLangevinKokkos::cleanup_copy() { random = nullptr; tstr = nullptr; gfactor1 = nullptr; gfactor2 = nullptr; ratio = nullptr; id_temp = nullptr; flangevin = nullptr; tforce = nullptr; gjfflag = 0; franprev = nullptr; lv = nullptr; id = style = nullptr; vatom = nullptr; } namespace LAMMPS_NS { template class FixLangevinKokkos; #ifdef LMP_KOKKOS_GPU template class FixLangevinKokkos; #endif }