|
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