Skip to content

Commit b9f2f56

Browse files
Merge pull request #1424 from Iximiel/singleScalarWall
Poposing: compacting lower and upper walls into a single file
2 parents e94d93c + c293e97 commit b9f2f56

2 files changed

Lines changed: 101 additions & 185 deletions

File tree

src/bias/UWalls.cpp

Lines changed: 0 additions & 172 deletions
This file was deleted.
Lines changed: 101 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,55 @@
2525
namespace PLMD {
2626
namespace 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+
If the inputs to the arguments are scalars the restraining potential starts acting on the system when the value of the CV is greater
34+
than a certain limit $a_i$ (AT) minus an offset $o_i$ (OFFSET). The expression for the bias due to the wall is given by:
35+
36+
$$
37+
\sum_i {k_i}((x_i-a_i+o_i)/s_i)^e_i
38+
$$
39+
40+
In this expression $k_i$ (KAPPA) is an energy constant in internal unit of the code, $s_i$ (EPS) a rescaling factor and
41+
$e_i$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFFSET = 0.
42+
43+
The following input tells plumed to add both a lower and an upper walls on the distance
44+
between atoms 3 and 5 and the distance between atoms 2 and 4. The lower and upper limits
45+
are defined at different values. The strength of the walls is the same for the four cases.
46+
It also tells plumed to print the energy of the walls.
47+
48+
```plumed
49+
d1: DISTANCE ATOMS=3,5
50+
d2: DISTANCE ATOMS=2,4
51+
uwall: UPPER_WALLS ARG=d1,d2 AT=1.0,1.5 KAPPA=150.0,150.0 EXP=2,2 EPS=1,1 OFFSET=0,0
52+
lwall: LOWER_WALLS ARG=d1,d2 AT=0.0,1.0 KAPPA=150.0,150.0 EXP=2,2 EPS=1,1 OFFSET=0,0
53+
PRINT ARG=uwall.bias,lwall.bias
54+
```
55+
56+
Alternatively, if the input to this action is a vector as in the example shown below:
57+
58+
```plumed
59+
d1: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6
60+
uwall: UPPER_WALLS ARG=d1 AT=1.0 KAPPA=150.0 EXP=2 EPS=1 OFFSET=0
61+
PRINT ARG=uwall.bias
62+
```
63+
64+
The bias that acts is given by the following expression:
65+
66+
$$
67+
\sum_i \sum_j {k_i}((x_{ij}-a_i+o_i)/s_i)^e_i
68+
$$
69+
70+
The sum over $i$ here is runs over the two arguments, while the sum over $j$ runs over the three components of the input vectors.
71+
Notice, that regardless of whether the input is a scalar, vector or matrix the number of $k_i$, $a_i$, $o_i$, $e_i$ and $s_i$ values must be
72+
equal to the number of arguments to the action.
73+
74+
*/
75+
//+ENDPLUMEDOC
76+
2877
//+PLUMEDOC BIAS LOWER_WALLS
2978
/*
3079
Defines a wall for the value of one or more collective variables,
@@ -74,23 +123,58 @@ equal to the number of arguments to the action.
74123
*/
75124
//+ENDPLUMEDOC
76125

77-
class LWalls : public Bias {
126+
enum class WallType {UPPER,LOWER};
127+
128+
template<WallType W>
129+
class WallsScalar : public Bias {
78130
std::vector<double> at;
79131
std::vector<double> kappa;
80132
std::vector<double> exp;
81133
std::vector<double> eps;
82134
std::vector<double> offset;
135+
static constexpr auto force2="force2";
136+
inline double walloff(double cv, double off) {
137+
if constexpr(W==WallType::UPPER) {
138+
return cv+off;
139+
} else {
140+
return cv-off;
141+
}
142+
}
143+
inline double wallpow(double scale, double exponent) {
144+
if constexpr(W==WallType::UPPER) {
145+
return std::pow(scale,exponent);
146+
} else {
147+
return std::pow(-scale,exponent);
148+
}
149+
}
150+
inline bool check(double scale) {
151+
if constexpr(W==WallType::UPPER) {
152+
return scale > 0.0;
153+
} else {
154+
return scale < 0.0;
155+
}
156+
}
83157
public:
84-
explicit LWalls(const ActionOptions&);
158+
explicit WallsScalar(const ActionOptions&);
85159
void calculate() override;
86160
static void registerKeywords(Keywords& keys);
87161
};
88162

163+
using UWalls = WallsScalar<WallType::UPPER>;
164+
PLUMED_REGISTER_ACTION(UWalls,"UPPER_WALLS_SCALAR")
165+
166+
using LWalls = WallsScalar<WallType::LOWER>;
89167
PLUMED_REGISTER_ACTION(LWalls,"LOWER_WALLS_SCALAR")
90168

91-
void LWalls::registerKeywords(Keywords& keys) {
169+
template<WallType W>
170+
void WallsScalar<W>::registerKeywords(Keywords& keys) {
92171
Bias::registerKeywords(keys);
93-
keys.setDisplayName("LOWER_WALLS");
172+
if constexpr(W==WallType::UPPER) {
173+
keys.setDisplayName("UPPER_WALLS");
174+
} else {
175+
keys.setDisplayName("LOWER_WALLS");
176+
}
177+
94178
keys.add("hidden","NO_ACTION_LOG","suppresses printing from action on the log");
95179
keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall.");
96180
keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall.");
@@ -100,7 +184,8 @@ void LWalls::registerKeywords(Keywords& keys) {
100184
keys.addOutputComponent("force2","default","scalar","the instantaneous value of the squared force due to this bias potential");
101185
}
102186

103-
LWalls::LWalls(const ActionOptions&ao):
187+
template<WallType W>
188+
WallsScalar<W>::WallsScalar(const ActionOptions&ao):
104189
PLUMED_BIAS_INIT(ao),
105190
at(getNumberOfArguments(),0),
106191
kappa(getNumberOfArguments(),0.0),
@@ -141,31 +226,34 @@ LWalls::LWalls(const ActionOptions&ao):
141226
}
142227
log.printf("\n");
143228

144-
addComponent("force2");
145-
componentIsNotPeriodic("force2");
229+
addComponent(force2);
230+
componentIsNotPeriodic(force2);
146231
}
147232

148-
void LWalls::calculate() {
233+
234+
235+
template<WallType W>
236+
void WallsScalar<W>::calculate() {
149237
double ene = 0.0;
150238
double totf2 = 0.0;
151239
for(unsigned i=0; i<getNumberOfArguments(); ++i) {
152240
double f = 0.0;
153241
const double cv=difference(i,at[i],getArgument(i));
154242
const double off=offset[i];
155243
const double epsilon=eps[i];
156-
const double lscale = (cv-off)/epsilon;
157-
if( lscale < 0.) {
244+
const double scale = walloff(cv,off)/epsilon;
245+
if( check(scale) ) {
158246
const double k=kappa[i];
159247
const double exponent=exp[i];
160-
double power = std::pow( -lscale, exponent );
161-
f = -( k / epsilon ) * exponent * power / lscale;
248+
double power = wallpow( scale, exponent );
249+
f = -( k / epsilon ) * exponent * power / scale;
162250
ene += k * power;
163251
totf2 += f * f;
164252
}
165253
setOutputForce(i,f);
166254
}
167255
setBias(ene);
168-
getPntrToComponent("force2")->set(totf2);
256+
getPntrToComponent(force2)->set(totf2);
169257
}
170258

171259
}

0 commit comments

Comments
 (0)