1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2012-2021 The plumed team
3 (see the PEOPLE file at the root of the distribution for a list of names)
4
5 See http://www.plumed.org for more information.
6
7 This file is part of plumed, version 2.
8
9 plumed is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 plumed is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #include "Bias.h"
23 #include "ActionRegister.h"
24
25
26 using namespace std;
27
28
29 namespace PLMD {
30 namespace bias {
31
32 //+PLUMEDOC BIAS LOWER_WALLS
33 /*
34 Defines a wall for the value of one or more collective variables,
35 which limits the region of the phase space accessible during the simulation.
36
37 The restraining potential starts acting on the system when the value of the CV is greater
38 (in the case of UPPER_WALLS) or lower (in the case of LOWER_WALLS) than a certain limit \f$a_i\f$ (AT)
39 minus an offset \f$o_i\f$ (OFFSET).
40 The expression for the bias due to the wall is given by:
41
42 \f$
43 \sum_i {k_i}((x_i-a_i+o_i)/s_i)^e_i
44 \f$
45
46 \f$k_i\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s_i\f$ (EPS) a rescaling factor and
47 \f$e_i\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFFSET = 0.
48
49
50 \par Examples
51
52 The following input tells plumed to add both a lower and an upper walls on the distance
53 between atoms 3 and 5 and the distance between atoms 2 and 4. The lower and upper limits
54 are defined at different values. The strength of the walls is the same for the four cases.
55 It also tells plumed to print the energy of the walls.
56 \plumedfile
57 DISTANCE ATOMS=3,5 LABEL=d1
58 DISTANCE ATOMS=2,4 LABEL=d2
59 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
60 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
61 PRINT ARG=uwall.bias,lwall.bias
62 \endplumedfile
63 (See also \ref DISTANCE and \ref PRINT).
64
65 */
66 //+ENDPLUMEDOC
67
68 class LWalls : public Bias {
69 std::vector<double> at;
70 std::vector<double> kappa;
71 std::vector<double> exp;
72 std::vector<double> eps;
73 std::vector<double> offset;
74 public:
75 explicit LWalls(const ActionOptions&);
76 void calculate() override;
77 static void registerKeywords(Keywords& keys);
78 };
79
80 PLUMED_REGISTER_ACTION(LWalls,"LOWER_WALLS")
81
registerKeywords(Keywords & keys)82 void LWalls::registerKeywords(Keywords& keys) {
83 Bias::registerKeywords(keys);
84 keys.use("ARG");
85 keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall.");
86 keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall.");
87 keys.add("compulsory","OFFSET","0.0","the offset for the start of the wall. The o_i in the expression for a wall.");
88 keys.add("compulsory","EXP","2.0","the powers for the walls. The e_i in the expression for a wall.");
89 keys.add("compulsory","EPS","1.0","the values for s_i in the expression for a wall");
90 keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential");
91 }
92
LWalls(const ActionOptions & ao)93 LWalls::LWalls(const ActionOptions&ao):
94 PLUMED_BIAS_INIT(ao),
95 at(getNumberOfArguments(),0),
96 kappa(getNumberOfArguments(),0.0),
97 exp(getNumberOfArguments(),2.0),
98 eps(getNumberOfArguments(),1.0),
99 offset(getNumberOfArguments(),0.0)
100 {
101 // Note sizes of these vectors are automatically checked by parseVector :-)
102 parseVector("OFFSET",offset);
103 parseVector("EPS",eps);
104 parseVector("EXP",exp);
105 parseVector("KAPPA",kappa);
106 parseVector("AT",at);
107 checkRead();
108
109 log.printf(" at");
110 for(unsigned i=0; i<at.size(); i++) log.printf(" %f",at[i]);
111 log.printf("\n");
112 log.printf(" with an offset");
113 for(unsigned i=0; i<offset.size(); i++) log.printf(" %f",offset[i]);
114 log.printf("\n");
115 log.printf(" with force constant");
116 for(unsigned i=0; i<kappa.size(); i++) log.printf(" %f",kappa[i]);
117 log.printf("\n");
118 log.printf(" and exponent");
119 for(unsigned i=0; i<exp.size(); i++) log.printf(" %f",exp[i]);
120 log.printf("\n");
121 log.printf(" rescaled");
122 for(unsigned i=0; i<eps.size(); i++) log.printf(" %f",eps[i]);
123 log.printf("\n");
124
125 addComponent("force2"); componentIsNotPeriodic("force2");
126 }
127
calculate()128 void LWalls::calculate() {
129 double ene = 0.0;
130 double totf2 = 0.0;
131 for(unsigned i=0; i<getNumberOfArguments(); ++i) {
132 double f = 0.0;
133 const double cv=difference(i,at[i],getArgument(i));
134 const double off=offset[i];
135 const double epsilon=eps[i];
136 const double lscale = (cv-off)/epsilon;
137 if( lscale < 0.) {
138 const double k=kappa[i];
139 const double exponent=exp[i];
140 double power = pow( lscale, exponent );
141 f = -( k / epsilon ) * exponent * power / lscale;
142 ene += k * power;
143 totf2 += f * f;
144 }
145 setOutputForce(i,f);
146 }
147 setBias(ene);
148 getPntrToComponent("force2")->set(totf2);
149 }
150
151 }
152 }
153