2525namespace PLMD {
2626namespace bias {
2727
28+ // +PLUMEDOC BIAS UPPER_WALLS
29+ /*
30+ Defines a wall for the value of one or more collective variables,
31+ which limits the region of the phase space accessible during the simulation.
32+
33+ The restraining potential starts acting on the system when the value of the CV is greater
34+ (in the case of UPPER_WALLS) or lower (in the case of LOWER_WALLS) than a certain limit \f$a_i\f$ (AT)
35+ minus an offset \f$o_i\f$ (OFFSET).
36+ The expression for the bias due to the wall is given by:
37+
38+ \f$
39+ \sum_i {k_i}((x_i-a_i+o_i)/s_i)^e_i
40+ \f$
41+
42+ \f$k_i\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s_i\f$ (EPS) a rescaling factor and
43+ \f$e_i\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFFSET = 0.
44+
45+
46+ \par Examples
47+
48+ The following input tells plumed to add both a lower and an upper walls on the distance
49+ between atoms 3 and 5 and the distance between atoms 2 and 4. The lower and upper limits
50+ are defined at different values. The strength of the walls is the same for the four cases.
51+ It also tells plumed to print the energy of the walls.
52+ \plumedfile
53+ DISTANCE ATOMS=3,5 LABEL=d1
54+ DISTANCE ATOMS=2,4 LABEL=d2
55+ UPPER_WALLS ARG=d1,d2 AT=1.0,1.5 KAPPA=150.0,150.0 EXP=2,2 EPS=1,1 OFFSET=0,0 LABEL=uwall
56+ LOWER_WALLS ARG=d1,d2 AT=0.0,1.0 KAPPA=150.0,150.0 EXP=2,2 EPS=1,1 OFFSET=0,0 LABEL=lwall
57+ PRINT ARG=uwall.bias,lwall.bias
58+ \endplumedfile
59+ (See also \ref DISTANCE and \ref PRINT).
60+
61+ */
62+ // +ENDPLUMEDOC
63+
64+ // +PLUMEDOC BIAS UPPER_WALLS_SCALAR
65+ /*
66+ Defines a wall for the value of one or more collective variables,
67+ which limits the region of the phase space accessible during the simulation.
68+
69+ \par Examples
70+
71+ */
72+ // +ENDPLUMEDOC
73+
2874// +PLUMEDOC BIAS LOWER_WALLS
2975/*
3076Defines a wall for the value of one or more collective variables,
@@ -71,22 +117,58 @@ Defines a wall for the value of one or more collective variables,
71117*/
72118// +ENDPLUMEDOC
73119
74- class LWalls : public Bias {
120+ enum class WallType {UPPER,LOWER};
121+
122+ template <WallType W>
123+ class WallsScalar : public Bias {
75124 std::vector<double > at;
76125 std::vector<double > kappa;
77126 std::vector<double > exp;
78127 std::vector<double > eps;
79128 std::vector<double > offset;
129+ static constexpr auto force2=" force2" ;
130+ inline double constexpr walloff (double cv, double off) {
131+ if constexpr (W==WallType::UPPER) {
132+ return cv+off;
133+ } else {
134+ return cv-off;
135+ }
136+ }
137+ inline double constexpr wallpow (double scale, double exponent) {
138+ if constexpr (W==WallType::UPPER) {
139+ return std::pow (scale,exponent);
140+ } else {
141+ return std::pow (-scale,exponent);
142+ }
143+ }
144+ inline bool constexpr check (double scale) {
145+ if constexpr (W==WallType::UPPER) {
146+ return scale > 0.0 ;
147+ } else {
148+ return scale < 0.0 ;
149+ }
150+ }
80151public:
81- explicit LWalls (const ActionOptions&);
152+ explicit WallsScalar (const ActionOptions&);
82153 void calculate () override ;
83154 static void registerKeywords (Keywords& keys);
84155};
85156
157+ using UWalls = WallsScalar<WallType::UPPER>;
158+ PLUMED_REGISTER_ACTION (UWalls," UPPER_WALLS_SCALAR" )
159+
160+ using LWalls = WallsScalar<WallType::LOWER>;
86161PLUMED_REGISTER_ACTION (LWalls," LOWER_WALLS_SCALAR" )
87162
88- void LWalls::registerKeywords (Keywords& keys) {
89- Bias::registerKeywords (keys); keys.setDisplayName (" LOWER_WALLS" );
163+ template <WallType W>
164+ void WallsScalar<W>::registerKeywords(Keywords& keys) {
165+ Bias::registerKeywords (keys);
166+ if constexpr (W==WallType::UPPER) {
167+ keys.setDisplayName (" UPPER_WALLS" );
168+ } else {
169+ keys.setDisplayName (" LOWER_WALLS" );
170+ }
171+
90172 keys.use (" ARG" ); keys.add (" hidden" ," NO_ACTION_LOG" ," suppresses printing from action on the log" );
91173 keys.add (" compulsory" ," AT" ," the positions of the wall. The a_i in the expression for a wall." );
92174 keys.add (" compulsory" ," KAPPA" ," the force constant for the wall. The k_i in the expression for a wall." );
@@ -96,7 +178,8 @@ void LWalls::registerKeywords(Keywords& keys) {
96178 keys.addOutputComponent (" force2" ," default" ," the instantaneous value of the squared force due to this bias potential" );
97179}
98180
99- LWalls::LWalls (const ActionOptions&ao):
181+ template <WallType W>
182+ WallsScalar<W>::WallsScalar(const ActionOptions&ao):
100183 PLUMED_BIAS_INIT (ao),
101184 at(getNumberOfArguments(),0),
102185 kappa(getNumberOfArguments(),0.0),
@@ -128,30 +211,33 @@ LWalls::LWalls(const ActionOptions&ao):
128211 for (unsigned i=0 ; i<eps.size (); i++) log.printf (" %f" ,eps[i]);
129212 log.printf (" \n " );
130213
131- addComponent (" force2" ); componentIsNotPeriodic (" force2" );
214+ addComponent (force2); componentIsNotPeriodic (force2);
132215}
133216
134- void LWalls::calculate () {
217+
218+
219+ template <WallType W>
220+ void WallsScalar<W>::calculate() {
135221 double ene = 0.0 ;
136222 double totf2 = 0.0 ;
137223 for (unsigned i=0 ; i<getNumberOfArguments (); ++i) {
138224 double f = 0.0 ;
139225 const double cv=difference (i,at[i],getArgument (i));
140226 const double off=offset[i];
141227 const double epsilon=eps[i];
142- const double lscale = (cv- off)/epsilon;
143- if ( lscale < 0 . ) {
228+ const double scale = walloff (cv, off)/epsilon;
229+ if ( check (scale) ) {
144230 const double k=kappa[i];
145231 const double exponent=exp[i];
146- double power = std::pow ( lscale , exponent );
147- f = -( k / epsilon ) * exponent * power / lscale ;
232+ double power = wallpow ( scale , exponent );
233+ f = -( k / epsilon ) * exponent * power / scale ;
148234 ene += k * power;
149235 totf2 += f * f;
150236 }
151237 setOutputForce (i,f);
152238 }
153239 setBias (ene);
154- getPntrToComponent (" force2" )->set (totf2);
240+ getPntrToComponent (force2)->set (totf2);
155241}
156242
157243}
0 commit comments