|
2 | 2 | // Copyright (c) 2021-2024, Auburn University |
3 | 3 | // Part of azplugins, released under the BSD 3-Clause License. |
4 | 4 |
|
5 | | -/*! \file BondEvaluatorDoubleWell.h |
6 | | - \brief Defines the bond evaluator class for a double well potential |
7 | | -*/ |
8 | | - |
9 | 5 | #ifndef AZPLUGINS_BOND_EVALUATOR_DOUBLE_WELL_H_ |
10 | 6 | #define AZPLUGINS_BOND_EVALUATOR_DOUBLE_WELL_H_ |
11 | 7 |
|
12 | | -#ifndef NVCC |
| 8 | +#ifndef __HIPCC__ |
13 | 9 | #include <string> |
14 | 10 | #endif |
15 | 11 |
|
16 | | -#include "hoomd/HOOMDMath.h" |
| 12 | +#include "BondEvaluator.h" |
17 | 13 |
|
18 | | -#ifdef NVCC |
| 14 | +#ifdef __HIPCC__ |
19 | 15 | #define DEVICE __device__ |
20 | 16 | #else |
21 | 17 | #define DEVICE |
22 | 18 | #endif |
23 | 19 |
|
| 20 | +namespace hoomd |
| 21 | + { |
24 | 22 | namespace azplugins |
25 | 23 | { |
26 | 24 | namespace detail |
27 | 25 | { |
28 | 26 |
|
29 | | -//! Class for evaluating the double well bond potential |
30 | | -/*! |
31 | | -This bond potential follows the functional form |
32 | | -\f{eqnarray*} |
33 | | -
|
34 | | -V_{\rm{DW}}(r) = \frac{V_{max}-c/2}{b^4} \left[ \left( r - a/2 \right)^2 -b^2 \right]^2 + |
35 | | -\frac{c}{2b}\left(r-a/2\right)+c/2 |
36 | | -
|
37 | | -\f} |
38 | | -which has two minima at r = (a/2 +/- b), seperated by a maximum at a/2 of height V_max when c is set |
39 | | -to zero. |
40 | | -
|
41 | | -The parameter a tunes the location of the maximal value and the parameter b tunes the distance of |
42 | | -the two maxima from each other. This potential is useful to model bonds which can be either |
43 | | -mechanically or thermally "activated" into a effectively longer state. The value of V_max can be |
44 | | -used to tune the height of the energy barrier in between the two states. |
45 | | -
|
46 | | -If c is non zero, the relative energy of the minima can be tuned, where c is the energy of the |
47 | | -second minima, the first minima value is at zero. This causes a small shift in the location of the |
48 | | -minima and the maxima, because of the added linear term. |
49 | | -
|
50 | | -The parameters are: |
51 | | - - \a V_max (params.x) potential difference between the the first minima and maxima |
52 | | - - \a a (params.y) shift for the location of the V_max, the maximum is at approx. a/2 |
53 | | - - \a b (params.z) scaling for the distance of the two minima at approx. (a/2 +/- b) |
54 | | - - \a c (params.w) potential difference between the two minima, default is c=0 |
55 | | -
|
56 | | -*/ |
57 | | -class BondEvaluatorDoubleWell |
| 27 | +//! Parameters of double well bond potential |
| 28 | +struct BondParametersDoubleWell : public BondParameters |
58 | 29 | { |
59 | | - public: |
60 | | - //! Define the parameter type used by this bond potential evaluator |
61 | | - |
62 | | - typedef Scalar4 param_type; |
| 30 | +#ifndef __HIPCC__ |
| 31 | + BondParametersDoubleWell() : r_1(0), r_diff(1.0), U_1(0), U_tilt(0) { } |
63 | 32 |
|
64 | | - //! Constructs the pair potential evaluator |
65 | | - /*! |
66 | | - * \param _rsq Squared distance beteen the particles |
67 | | - * \param _params Per type bond parameters of this potential as given above |
68 | | - */ |
69 | | - DEVICE BondEvaluatorDoubleWell(Scalar _rsq, const param_type& _params) |
70 | | - : rsq(_rsq), V_max(_params.x), a(_params.y), b(_params.z), c(_params.w) |
| 33 | + BondParametersDoubleWell(pybind11::dict v) |
71 | 34 | { |
| 35 | + r_1 = v["r_1"].cast<Scalar>(); |
| 36 | + r_diff = r_1 - v["r_0"].cast<Scalar>(); |
| 37 | + U_1 = v["U_1"].cast<Scalar>(); |
| 38 | + U_tilt = v["U_tilt"].cast<Scalar>(); |
72 | 39 | } |
73 | 40 |
|
74 | | - //! This evaluator doesn't use diameter information |
75 | | - DEVICE static bool needsDiameter() |
| 41 | + pybind11::dict asDict() |
76 | 42 | { |
77 | | - return false; |
| 43 | + pybind11::dict v; |
| 44 | + v["r_0"] = r_1 - r_diff; |
| 45 | + v["r_1"] = r_1; |
| 46 | + v["U_1"] = U_1; |
| 47 | + v["U_tilt"] = U_tilt; |
| 48 | + return v; |
78 | 49 | } |
| 50 | +#endif |
| 51 | + |
| 52 | + Scalar r_1; //!< location of the potential local maximum |
| 53 | + Scalar r_diff; //!< difference between r_1 and r_0 (location of first minimum) |
| 54 | + Scalar U_1; //!< Potential Potential maximum energy barrier between minima |
| 55 | + Scalar U_tilt; //!< tunes the energy offset (tilt) between minima |
| 56 | + } |
| 57 | +#if HOOMD_LONGREAL_SIZE == 32 |
| 58 | + __attribute__((aligned(16))); |
| 59 | +#else |
| 60 | + __attribute__((aligned(32))); |
| 61 | +#endif |
79 | 62 |
|
80 | | - //! Accept the optional diameter values |
81 | | - /*! |
82 | | - * \param da Diameter of particle a |
83 | | - * \param db Diameter of particle b |
84 | | - */ |
85 | | - DEVICE void setDiameter(Scalar da, Scalar db) { } |
| 63 | +//! Class for evaluating the double well bond potential |
| 64 | +/*! |
| 65 | + * This bond potential follows the functional form |
| 66 | + * \f{eqnarray*} |
| 67 | + * |
| 68 | + * U(r) = U_1\left[\frac{\left((r-r_1)^2-(r_1-r_0)^2\right)^2}{\left(r_1-r_0\right)^4}\right] |
| 69 | + * + |
| 70 | + * U_{\rm{tilt}}\left[1+\frac{r-r_1}{r_1-r_0}-\frac{\left((r-r_1)^2-(r_1-r_0)^2\right)^2}{\left(r_1-r_0\right)^4}\right] |
| 71 | + * |
| 72 | + * \f} |
| 73 | + * which has two minima at r = r_0 and r = 2 * r_1 - r_0, seperated by a maximum |
| 74 | + * at r_1 of height U_1 when U_tilt is set to zero. |
| 75 | + * |
| 76 | + * The parameter r_1 tunes the location of the maximal value and the parameter r_0 tunes the |
| 77 | + * distance of the two minima from each other. This potential is useful to model bonds which can be |
| 78 | + * either mechanically or thermally "activated" into a effectively longer state. The value of U_1 |
| 79 | + * can be used to tune the height of the energy barrier in between the two states. |
| 80 | + * |
| 81 | + * If U_tilt is non zero, the relative energy of the minima can be tuned, where 2 * U_tilt |
| 82 | + * is the energy of the second minima, the first minima value is at zero. This causes a |
| 83 | + * small shift in the location of the minima and the maxima, because of the added linear term. |
| 84 | + */ |
| 85 | +class BondEvaluatorDoubleWell : public BondEvaluator |
| 86 | + { |
| 87 | + public: |
| 88 | + typedef BondParametersDoubleWell param_type; |
86 | 89 |
|
87 | | - //! This evaluator doesn't use charge |
88 | | - DEVICE static bool needsCharge() |
| 90 | + DEVICE BondEvaluatorDoubleWell(Scalar _rsq, const param_type& _params) |
| 91 | + : BondEvaluator(_rsq), r_1(_params.r_1), r_diff(_params.r_diff), U_1(_params.U_1), |
| 92 | + U_tilt(_params.U_tilt) |
89 | 93 | { |
90 | | - return false; |
91 | 94 | } |
92 | 95 |
|
93 | | - //! Accept the optional charge values |
94 | | - /*! |
95 | | - * \param qa Charge of particle a |
96 | | - * \param qb Charge of particle b |
97 | | - */ |
98 | | - DEVICE void setCharge(Scalar qa, Scalar qb) { } |
99 | | - |
100 | | - //! Evaluate the force and energy |
101 | | - /*! |
102 | | - * \param force_divr Output parameter to write the computed force divided by r. |
103 | | - * \param bond_eng Output parameter to write the computed bond energy |
104 | | - * |
105 | | - * \return True if they are evaluated or false if the bond energy is not defined. |
106 | | - */ |
107 | 96 | DEVICE bool evalForceAndEnergy(Scalar& force_divr, Scalar& bond_eng) |
108 | 97 | { |
109 | 98 | bond_eng = 0; |
110 | 99 | force_divr = 0; |
111 | | - |
112 | | - // check for invalid parameters |
113 | | - if (b == Scalar(0.0)) |
| 100 | + // check for invalid parameters r0 = r1 |
| 101 | + if (r_diff == Scalar(0.0)) |
114 | 102 | return false; |
115 | 103 |
|
116 | | - Scalar c_half = Scalar(0.5) * c; |
117 | | - Scalar r = fast::sqrt(rsq); |
118 | | - Scalar r_min_half_a = r - Scalar(0.5) * a; |
119 | | - Scalar b_sq = b * b; |
120 | | - Scalar d = r_min_half_a * r_min_half_a - b_sq; |
121 | | - |
122 | | - bond_eng = ((V_max - c_half) / (b_sq * b_sq)) * d * d + c_half / b * r_min_half_a + c_half; |
123 | | - force_divr = -(4 * (V_max - c_half) / (b_sq * b_sq) * d * r_min_half_a + c_half / b) / r; |
| 104 | + const Scalar r = fast::sqrt(rsq); |
| 105 | + const Scalar x = (r_1 - r) / r_diff; |
| 106 | + const Scalar x2 = x * x; |
| 107 | + const Scalar y = Scalar(1.0) - x2; |
| 108 | + const Scalar y2 = y * y; |
124 | 109 |
|
| 110 | + bond_eng = U_1 * y2 + U_tilt * (Scalar(1.0) - x - y2); |
| 111 | + force_divr = (Scalar(4.0) * x * y * (U_tilt - U_1) - U_tilt) / (r_diff * r); |
125 | 112 | return true; |
126 | 113 | } |
127 | 114 |
|
128 | | -#ifndef NVCC |
129 | | - //! Get the name of this potential |
130 | | - /*! |
131 | | - * \returns The potential name. Must be short and all lowercase, as this is the name energies |
132 | | - * will be logged as via analyze.log. |
133 | | - */ |
| 115 | +#ifndef __HIPCC__ |
134 | 116 | static std::string getName() |
135 | 117 | { |
136 | | - return std::string("doublewell"); |
| 118 | + return std::string("DoubleWell"); |
137 | 119 | } |
138 | 120 | #endif |
139 | 121 |
|
140 | | - protected: |
141 | | - Scalar rsq; //!< Stored rsq from the constructor |
142 | | - Scalar V_max; //!< V_max parameter |
143 | | - Scalar a; //!< a parameter |
144 | | - Scalar b; //!< b parameter |
145 | | - Scalar c; //!< c parameter |
| 122 | + private: |
| 123 | + Scalar r_1; //!< r_1 parameter |
| 124 | + Scalar r_diff; //!< r_diff parameter |
| 125 | + Scalar U_1; //!< U_1 parameter |
| 126 | + Scalar U_tilt; //!< U_tilt parameter |
146 | 127 | }; |
147 | 128 |
|
148 | 129 | } // end namespace detail |
149 | 130 | } // end namespace azplugins |
| 131 | + } // end namespace hoomd |
150 | 132 |
|
151 | 133 | #undef DEVICE |
152 | 134 |
|
|
0 commit comments