|
| 1 | +// Copyright (c) 2009-2025 The Regents of the University of Michigan. |
| 2 | +// Part of HOOMD-blue, released under the BSD 3-Clause License. |
| 3 | + |
| 4 | +#ifndef __PAIR_EVALUATOR_WANGFRENKEL_H__ |
| 5 | +#define __PAIR_EVALUATOR_WANGFRENKEL_H__ |
| 6 | + |
| 7 | +#ifndef __HIPCC__ |
| 8 | +#include <string> |
| 9 | +#endif |
| 10 | + |
| 11 | +#include "hoomd/HOOMDMath.h" |
| 12 | + |
| 13 | +/*! \file EvaluatorPairWangFrenkel.h |
| 14 | + \brief Defines the pair evaluator class for Wang-Frenkel potentials |
| 15 | +*/ |
| 16 | + |
| 17 | +// need to declare these class methods with __device__ qualifiers when building in nvcc |
| 18 | +// DEVICE is __host__ __device__ when included in nvcc and blank when included into the host |
| 19 | +// compiler |
| 20 | +#ifdef __HIPCC__ |
| 21 | +#define DEVICE __device__ |
| 22 | +#define HOSTDEVICE __host__ __device__ |
| 23 | +#else |
| 24 | +#define DEVICE |
| 25 | +#define HOSTDEVICE |
| 26 | +#endif |
| 27 | + |
| 28 | +namespace hoomd |
| 29 | + { |
| 30 | +namespace md |
| 31 | + { |
| 32 | +//! Class for evaluating the Wang-Frenkel pair potential |
| 33 | +/*! <b>General Overview</b> |
| 34 | +
|
| 35 | + See EvaluatorPairLJ. |
| 36 | +
|
| 37 | + <b>Wang-Frenkel specifics</b> |
| 38 | +
|
| 39 | + EvaluatorPairWang-Frenkel evaluates the function: |
| 40 | + \f[ \epsilon \alpha \left( \left[\frac{\sigma}{r}\right]^{2\mu} |
| 41 | + -1\right)\left(\left[\frac{R}{r}\right]^{2\mu} -1 \left)^{2\nu} \f] |
| 42 | +*/ |
| 43 | +class EvaluatorPairWangFrenkel |
| 44 | + { |
| 45 | + public: |
| 46 | + //! Define the parameter type used by this pair potential evaluator |
| 47 | + struct param_type |
| 48 | + { |
| 49 | + Scalar prefactor; |
| 50 | + Scalar sigma_pow_2m; |
| 51 | + Scalar R_pow_2m; |
| 52 | + int mu; |
| 53 | + int nu; |
| 54 | + |
| 55 | + DEVICE void load_shared(char*& ptr, unsigned int& available_bytes) { } |
| 56 | + |
| 57 | + HOSTDEVICE void allocate_shared(char*& ptr, unsigned int& available_bytes) const { } |
| 58 | + |
| 59 | +#ifdef ENABLE_HIP |
| 60 | + // set CUDA memory hints |
| 61 | + void set_memory_hint() const { } |
| 62 | +#endif |
| 63 | + |
| 64 | +#ifndef __HIPCC__ |
| 65 | + param_type() : prefactor(0.0), sigma_pow_2m(0.0), R_pow_2m(0.0), mu(0.0), nu(0.0) { } |
| 66 | + |
| 67 | + param_type(pybind11::dict v, bool managed = false) |
| 68 | + { |
| 69 | + // should probably send a warning if exponents are large (eg >256) |
| 70 | + mu = v["mu"].cast<unsigned int>(); |
| 71 | + nu = v["nu"].cast<unsigned int>(); |
| 72 | + |
| 73 | + if (nu == 0 || mu == 0) |
| 74 | + throw std::invalid_argument("Cannot set exponents nu or mu to zero"); |
| 75 | + |
| 76 | + Scalar epsilon = v["epsilon"].cast<Scalar>(); |
| 77 | + Scalar sigma = v["sigma"].cast<Scalar>(); |
| 78 | + Scalar sigma_sq = sigma * sigma; |
| 79 | + Scalar rcut = v["R"].cast<Scalar>(); |
| 80 | + Scalar rcutsq = rcut * rcut; |
| 81 | + Scalar left = (1 + 2 * nu) / (2 * nu * (fast::pow(rcutsq / sigma_sq, mu) - 1)); |
| 82 | + Scalar alpha = 2 * nu * fast::pow(rcutsq / sigma_sq, mu) * fast::pow(left, 2 * nu + 1); |
| 83 | + |
| 84 | + prefactor = epsilon * alpha; |
| 85 | + R_pow_2m = fast::pow(rcutsq, mu); |
| 86 | + sigma_pow_2m = fast::pow(sigma_sq, mu); |
| 87 | + } |
| 88 | + |
| 89 | + pybind11::dict asDict() |
| 90 | + { |
| 91 | + pybind11::dict v; |
| 92 | + v["mu"] = mu; |
| 93 | + v["nu"] = nu; |
| 94 | + Scalar sigma = fast::pow(sigma_pow_2m, 1.0 / (2.0 * Scalar(mu))); |
| 95 | + v["sigma"] = sigma; |
| 96 | + Scalar sigma_sq = sigma * sigma; |
| 97 | + v["R"] = fast::pow(R_pow_2m, 1 / Scalar(2 * mu)); |
| 98 | + Scalar rcutsq = fast::pow(R_pow_2m, 1 / Scalar(mu)); |
| 99 | + Scalar left = (1 + 2 * nu) / (2 * nu * (fast::pow(rcutsq / sigma_sq, mu) - 1)); |
| 100 | + Scalar alpha = 2 * nu * fast::pow(rcutsq / sigma_sq, mu) * fast::pow(left, 2 * nu + 1); |
| 101 | + |
| 102 | + v["epsilon"] = prefactor / alpha; |
| 103 | + |
| 104 | + return v; |
| 105 | + } |
| 106 | +#endif |
| 107 | + } __attribute__((aligned(16))); |
| 108 | + |
| 109 | + //! Constructs the pair potential evaluator |
| 110 | + /*! \param _rsq Squared distance between the particles |
| 111 | + \param _rcutsq Squared distance at which the potential goes to 0 |
| 112 | + \param _params Per type pair parameters of this potential |
| 113 | + */ |
| 114 | + DEVICE EvaluatorPairWangFrenkel(Scalar _rsq, Scalar _rcutsq, const param_type& _params) |
| 115 | + : rsq(_rsq), rcutsq(_rcutsq), prefactor(_params.prefactor), |
| 116 | + sigma_pow_2m(_params.sigma_pow_2m), R_pow_2m(_params.R_pow_2m), mu(_params.mu), |
| 117 | + nu(_params.nu) |
| 118 | + { |
| 119 | + } |
| 120 | + |
| 121 | + //! Mie doesn't use charge |
| 122 | + DEVICE static bool needsCharge() |
| 123 | + { |
| 124 | + return false; |
| 125 | + } |
| 126 | + //! Accept the optional charge values. |
| 127 | + /*! \param qi Charge of particle i |
| 128 | + \param qj Charge of particle j |
| 129 | + */ |
| 130 | + DEVICE void setCharge(Scalar qi, Scalar qj) { } |
| 131 | + |
| 132 | + //! Evaluate the force and energy |
| 133 | + /*! \param force_divr Output parameter to write the computed force divided by r. |
| 134 | + \param pair_eng Output parameter to write the computed pair energy |
| 135 | + \param energy_shift If true, the potential must be shifted so that V(r) is continuous at the |
| 136 | + cutoff \note There is no need to check if rsq < rcutsq in this method. Cutoff tests are |
| 137 | + performed in PotentialPair. |
| 138 | +
|
| 139 | + \return True if they are evaluated or false if they are not because we are beyond the cutoff |
| 140 | + */ |
| 141 | + DEVICE bool evalForceAndEnergy(Scalar& force_divr, Scalar& pair_eng, bool energy_shift) |
| 142 | + { |
| 143 | + // compute the force divided by r in force_divr |
| 144 | + if (rsq < rcutsq && prefactor != 0) |
| 145 | + { |
| 146 | + Scalar r2inv = Scalar(1.0) / rsq; |
| 147 | + Scalar rinv_pow_2m = fast::pow(r2inv, mu); |
| 148 | + Scalar sigma_over_r_pow_2m = sigma_pow_2m * rinv_pow_2m; |
| 149 | + Scalar R_over_r_pow_2m = R_pow_2m * rinv_pow_2m; |
| 150 | + |
| 151 | + Scalar sigma_term = sigma_over_r_pow_2m - 1; |
| 152 | + Scalar R_term = R_over_r_pow_2m - 1; |
| 153 | + |
| 154 | + Scalar R_term_2num1 = fast::pow(R_term, 2 * nu - 1); |
| 155 | + Scalar R_term_2nu = R_term_2num1 * R_term; |
| 156 | + |
| 157 | + pair_eng = prefactor * sigma_term * R_term_2nu; |
| 158 | + force_divr = 2 * prefactor * mu * R_term_2num1 |
| 159 | + * (2 * nu * R_over_r_pow_2m * sigma_term + R_term * sigma_over_r_pow_2m) |
| 160 | + * r2inv; |
| 161 | + |
| 162 | + if (energy_shift) |
| 163 | + { |
| 164 | + Scalar rcinv_pow_2m = fast::pow(Scalar(1.0) / rcutsq, mu); |
| 165 | + Scalar sigma_over_rc_pow_2m = sigma_pow_2m * rcinv_pow_2m; |
| 166 | + Scalar R_over_rc_pow_2m = R_pow_2m * rcinv_pow_2m; |
| 167 | + Scalar rc_R_term_2nu = fast::pow(R_over_rc_pow_2m - 1, 2 * nu); |
| 168 | + pair_eng -= prefactor * (sigma_over_rc_pow_2m - 1) * rc_R_term_2nu; |
| 169 | + } |
| 170 | + return true; |
| 171 | + } |
| 172 | + else |
| 173 | + return false; |
| 174 | + } |
| 175 | + |
| 176 | + DEVICE Scalar evalPressureLRCIntegral() |
| 177 | + { |
| 178 | + return 0; |
| 179 | + } |
| 180 | + |
| 181 | + DEVICE Scalar evalEnergyLRCIntegral() |
| 182 | + { |
| 183 | + return 0; |
| 184 | + } |
| 185 | + |
| 186 | +#ifndef __HIPCC__ |
| 187 | + //! Get the name of this potential |
| 188 | + /*! \returns The potential name. |
| 189 | + */ |
| 190 | + static std::string getName() |
| 191 | + { |
| 192 | + return std::string("wangfrenkel"); |
| 193 | + } |
| 194 | + |
| 195 | + std::string getShapeSpec() const |
| 196 | + { |
| 197 | + throw std::runtime_error("Shape definition not supported for this pair potential."); |
| 198 | + } |
| 199 | +#endif |
| 200 | + |
| 201 | + protected: |
| 202 | + Scalar rsq; //!< Stored rsq from the constructor |
| 203 | + Scalar rcutsq; //!< Stored rcutsq from the constructor |
| 204 | + |
| 205 | + Scalar prefactor; //!< Prefactor (epsilon * alpha) |
| 206 | + Scalar sigma_pow_2m; //!< sigma^(2m) stored |
| 207 | + Scalar R_pow_2m; //!< R^(2m) stored |
| 208 | + unsigned int mu; //!< mu exponent |
| 209 | + unsigned int nu; //!< nu exponent |
| 210 | + }; |
| 211 | + |
| 212 | + } // end namespace md |
| 213 | + } // end namespace hoomd |
| 214 | + |
| 215 | +#endif // __PAIR_EVALUATOR_WANGFRENKEL_H__ |
0 commit comments